SQL need help to group my results - php

Hey guy im looking to display some data from my oracle DB. im looking to group it by common data/column but cant figure it out.
$stid = oci_parse($conn, " SELECT REQ.REQSTN_NO, REQ.WO_NO, REQ.COST_CENTRE_CD, REQ.ACCT_PRIME_CD, REQ.ACCT_SUBSDRY_CD, REQ.STOCK_CD
FROM TE.REQSTNREQ
WHERE REQ.DEPT_CD='ISN'");
oci_execute($stid);
while (($row = oci_fetch_array($stid, OCI_BOTH+OCI_RETURN_NULLS)) != false) {
echo $row['COST_CENTRE_CD']."-".$row['ACCT_PRIME_CD']."-".$row['ACCT_SUBSDRY_CD']." ".$row['WO_NO']." ".$row['REQSTN_NO']." ".$row['STOCK_CD']."<br />";
}
Im looking to create an output like this
Ive tried Group BY and SUM/COUNT but i dont know how to structure the code properly any help would be appreciated.

This is not a real database "grouping" -- it is a display issue: you want to group rows with common column values together and print each shared column value only once.
Such display issues are best left to the presentation layer of your application and best left out of the SQL/data model layer.
Nevertheless, here is a technique you can use to group common column values together and to print each value only once, using SQL.
(Since you didn't provide your data in text form, this example uses DBA_OBJECTS to illustrate the technique).
SELECT
-- Order the row_number () partitions the same way the overall query is ordered...
case when row_number() over (partition by object_type order by object_type, owner, object_name) = 1 THEN object_type ELSE NULL END object_type,
case when row_number() over (partition by object_type, owner order by object_type, owner, object_name) = 1 THEN owner ELSE NULL END owner,
object_name,
created, last_ddl_time
FROM dba_objects o
ORDER BY
-- Important to qualify columns in ORDER BY...
o.object_type, o.owner, o.object_name;
The idea is that case statements check to see if this is the first row in a new shared common value and, only if so, to print the column value. Otherwise, it prints NULL.

You would need to use an object-relational database to achieve such a result.
Edited answer:
In MySQL you can use the following function: GROUP_CONCAT:
See reference: https://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html#function_group-concat
I believe there is a similar solution in oracle. You would need to refer to the following question:
Is there any function in oracle similar to group_concat in mysql?

Related

PHP vs MySQL Null check

I have a database with very large number of records. More specifically I have a query with multiple sub-queries in it which fetch records and display on front end.
I want to show some default value if field contains NULL.
I wish to find out which of the below approach can give better performance. I am using MySQL approach for now, but it takes lot of time.
MySQL Approach
SELECT A.columnA,
IFNULL (( SELECT B.columnB FROM tableB B), 'default-value') AS columnB,
IFNULL (( SELECT C.columnC FROM tableC C), 'default-value') AS columnC,
IFNULL (( SELECT D.columnD FROM tableD D), 'default-value') AS columnD
FROM tableA A
WHERE 1=1
LIMIT 20
ORDER BY A.columnA ASC
PHP Approach
foreach($recordsFromDB as $record) {
if(is_null($record->columnB)) {
echo 'default-value';
} else {
echo $record->columnA;
}
}
There isn't a perfect way to do something in programming, therefore alot of solutions were found! so let's start from this point,
in my opinion, checking for null values should be using PHP, and then the handles you've gotten can be passed for further MySQL processing!
You obviously will have tough time processing all this amount of queries using just MySQL.
My advice, try checking null values and replacing them in php and if you had to deal with retrieving/fetching or inserting values in database hit MySQL

Database Group By error

I've been working with Mysql for a while, but this is the first time I've encountered this problem.
The thing is that I have a select query...
SELECT
transactions.inventoryid,
inventoryName,
inventoryBarcode,
inventoryControlNumber,
users.nombre,
users.apellido,
transactionid,
transactionNumber,
originalQTY,
updateQTY,
finalQTY,
transactionDate,
transactionState,
transactions.observaciones
FROM
transactions
LEFT JOIN
inventory ON inventory.inventoryid = transactions.inventoryid
LEFT JOIN
users ON transactions.userid = users.userid
GROUP BY
transactions.transactionNumber
ORDER BY
transactions.inventoryid
But the GROUP BY is eliminating 2 values from the QUERY.
In this case, when I output:
foreach($inventory->inventory as $values){
$transactionid[] = $values['inventoryid'];
}
It returns:
2,3,5
If I eliminate the GROUP BY Statement it returns
2,3,4,5,6
Which is the output I need for this particular case.
The question is:
Is there a reason for this to happen?
If I'm grouping by a transaction and that was supposed to affect the query, wouldn't it then return only 1 value?
Maybe I'm over thinking this one or been working too long on the code that I don't see the obvious flaw in my logic. But if someone can lend me a hand I would appreciate it.
In standard SQL you can only SELECT colums which are
contained in GROUP BY clause
(or) aggregate "colums", like MAX() or COUNT().
You need to consult the MySQL description of the interpretation they use for columns which are not contained by GROUP BY (and which are no aggregated column) MySQL Handling of GROUP BY to find out what happens here.
Do you need more information?

Can't understand this MySQL Query Purpose

I'm doing an internship as Web Developer, I'm a bit new and i'm here to ask your experience to clarify my doubts; while i was working on a website that someone else made i found this query:
$query = "SELECT a.upload_date, a.zipfile, a.lang, b.*
FROM something_uploadform as a , something2_stayinformed as b
WHERE a.uid_head =b.uid and a.zipfile<>'' order by ".$orderby." desc";
Can anyone help me to understand it? I thought that this piece of code picks a record and attach it to an a, isn't it?
Thanks everyone.
At a high level, this query is doing an implicit JOIN on two tables. Let's break it down:
The data is coming from two tables (AS gives the table an alias):
something_uploadform as "a" (this table will now be known as a)
something2_stayinformed as "b" (this table will now be known as b)
The columns being selected:
a.upload_date
a.zipfile
a.lang
b.* (All columns in table b)
The tables are being joined on the columns:
a.uid_head = b.uid
The filter being applied:
a.zipfile <> '' (where the column zipfile is not empty)
The sort being applied:
$orderby DESC (passed variable, sorted in descending order)
something_uploadform as a defines a as an alias for something_uploadform so you don't have to specify the full table name when selecting columns.

Sorting data using ORDER BY Clause in MYSQL

I have two type of deal in my form 1)One way relocation deal and 2)Regular deal.There is a table in my db -Vehicles.
vehicles table
=====================================================
id, pickuplocation, returnlocation, included location
Now when user choose One way relocation deal then in db, only id,pickuplocation,returnlocation will be inserted and the coloumn included location will be null. And when user choose Regular deal,the column pickuplocation,returnlocation wil be null only the coloumn id and included location will set.Problem is i want to sort the whole data using their location.I tried this query -
SELECT *
FROM vehicles
where 1=1
ORDER BY pickuplocation ASC,returnlocation ASC
But it will not giving proper result because some data having null in included location.how can i sort for all pickuplocation,returnlocation,exculded location
You want the IFNULL function
Try sorting by
IFNULL(returnlocation, includedlocation)
Got the solution.I used this query
(SELECT id,pickuplocation,returnlocation,deal_type FROM `vehicles` where deal_type = 1)
UNION
(SELECT id,included_location,excluded_location,deal_type FROM `vehicles` where deal_type = 2)
order by pickuplocation,returnlocation
I hope this will help someone who may run into a similar problem in the future.
SELECT *
FROM vehicles
where 1=1 AND ($condition)
ORDER BY pickuplocation ASC,returnlocation ASC
Assuming $condition will be something like field01=1 OR field2 >=1

Assign places in the rating (MySQL, PHP)

I have a MySQL database with the following columns:
id company rating_score rating_place
I have companies and rating scores for each company. So, my db looks like:
id company rating_score rating_place
75 Intel 356.23
34 Sun 287.49
etc.
How can I assign the places (my rating_place column is empty) based on the score using php and mysql?
Thank you!
While Andrew G. Johnson is correct, you may not need to even store this information in the database.
The answer I have for you is simple: "Why do you want to store this in the database?"
If you have actually have a good reason, then you have a few choices based on how static the data is. If the data is created then inserted all at once, then ORDER BY rating_score DESC at the end of your statement should do it (if rating_place is assigned automatically from 1).
Otherwise, I would do something in a dedicated PHP page that, once your 2 columns are read, assigns the rating_place. If you manually enter data into your database, it shouldn't hurt to have to open the page. If data collection is automated, go ahead and throw a call to the "update_places_page" that updates the rating.
Edit:
Another option is just to create a view for rating_score that takes the top 20 and orders reorders them, then select from the new view and the actual table based on rating_score.
If you are just trying sort by highest rating to lowest add this to the end of your SQL query:
ORDER BY rating_score DESC
Or lowest to highest:
ORDER BY rating_score ASC
If you still want to do this your way [which I'd advise against] try this:
UPDATE mytable SET rating_place=(SELECT COUNT(*)+1 FROM mytable tablecheck WHERE tablecheck.rating_score > mytable.rating_score)
How about this:
update mytable set rating_place =(select count(*)+1 from mytable intb where intb.rating_score>mytable.rating_score)
----edit (after comment)
aww sorry, you can't select from the same table that you're updating in mysql, so try it with a temp table:
create table mytemptable as
select #row := #row +1 as place, mytable.id
from mytable, (SELECT #row := 0) r
order by rating_score desc;
and then just a similar update:
update mytable set rating_place = (
select place
from mytemptable
where mytemptable.id=mytable.id
)
after that you can drop that mytemptable.
although if you want to avoid a separate table and you can use php, you can try
$res=mysql_query("select id from mytable order by rating_score desc");
$ratings=array();
while ($r=mysql_fetch_assoc($res)) {
$ratings[]=$r['id'];
}
foreach ($ratings as $key=>$val) {
mysql_query("update mytable set rating_score=".($key+1)." where id=".$val);
}
Just sort by rating! This approach is just wrong as you would have to shift modify all data above a certain rank if you insert something. Bad data structure.
Well if you only insert something once or twice a year you could argue that integer sorting is faster, but well thats just a very minimal difference as sorting is based on Tree indexes and not on comparision.
So I have seen solutions like Andrew G. Johnson's. You could also tweak this further and only update entries with a higher score.
You could also create a trigger that does it automatically for you.
But let me explain why this is wrong:
Its redundant data. Its not atomic and consistent.
In a good atabase design you should always (if possible) store every information only at one point so it can be modified, deleted in an atomic way.
So you can avoid any inconsistencies and complications in the first place.
If you really wan't to "cache" the ranking, do it in your application.
So what are your alternatives to this if you really want to have database fields called like this?
Create a mysql view based on the sorted query.
You can also do caching there AFAIK if thats your goal.
But the better option for caching would be just to let the mysql query cache do the work for you. That would be the very best option.
I see no reason what so ever to do what you are trying to do, only valid arguments against it.
SELECT #row := 0;
UPDATE
`table`
SET
`table`.`rating_place` = (#row := #row +1)
ORDER BY
`table`.`rating_score` DESC;
PS: If you will be sending the queries from PHP, you will need to split the two, since PHP MySQL extension normally allows only single query per call.
yourQueryFunc('SELECT #row := 0;');
yourQueryFunc('
SELECT #row := 0;
UPDATE
`table`
SET
`table`.`rating_place` = (#row := #row +1)
ORDER BY
`table`.`rating_score` DESC;');
I would do a select using the order by desc clause and then update each row with the rating.
It is probably a lot more convenient to work out the place as you go. To do this you would read the values and order by Rating_Score (ASC). Then they would be in order of place as you read them out. If you like, you could then write this back into the table, but this would mean you have to constantly update the place value. If this database is going to be constantly changing from user input or something, I would recommend working out the places as you go. If the table will remain mostly static, you could have a place column.

Categories