i have a table like this
id(pk)|product_id(fk)|serial(varchar)|status(varchar)
1 | 2 | e098 | sold
2 | 2 | e008 | faulty
what i need to extract is:
array(faulty=>1,sold=>1)
i i can do it with a complex query, is there any SIMPLE query which can help?
i tried this:
SELECT COUNT(id) as product_details.status FROM product_details WHERE product_id=2 GROUP BY status which didn't work.
(ab)Use mysql's auto-typecasting:
SELECT SUM(status='sold') AS sold, SUM(status='faulty') AS faulty
FROM ...
the boolean result of status='sold' will be typecast to integer 0/1 and then summed up.
The other option is just to do a regular query and then do the pivoting in client-side code:
SELECT id, status, COUNT(status) AS count
FROM ...
GROUP BY id, status
and then
while(... fetch ...) {
$results[$row['id']][$row['status']] = $row['count'];
}
You want to query status as well like this.
SELECT status, COUNT(id) as count FROM product_details WHERE product_id=2 GROUP BY status
Related
id | order_id | tracking | status | update_time
Table Name : ndc
1 100204835 124124304 0 2017-06-29 00:00:00
2 100204874 124104482 0 2017-06-29 00:00:00
3 100204835 124124304 0 2017-06-29 00:00:00
I need to SELECT all values (id,order_id,tracking_no) from ndc where order_id should be unique as there might be duplicate values.
The result should output all values in the row as I need to use them further.
For Ex. In the above table order_id 100204835 is duplicate.
Try this : Select * from ndc group by order_id;
You need to use DISTINCT with a field name and specifying other fields.
SQL: SELECT DISTINCT order_id, id,tracking,status,update_time FROM table
For more continent answer please follow-
MySQL - SELECT all columns WHERE one column is DISTINCT
use this
Select * from table group by order_id;
SELECT DISTINCT order_id,id,tracking_no FROM ndc;
also you can use it for distinct on multiple column
SELECT DISTINCT order_id FROM ndc
UNION
SELECT DISTINCT id FROM ndc
UNION
SELECT DISTINCT tracking_no FROM ndc
QUERY:
SELECT id,order_id,tracking_no,status,update_time, DISTINCT order_id FROM ndc;
or You Can Use Simple group by order_id;
Syntax: select * from table_name group by field_name;
NOTE: A DISTINCT and GROUP BY usually generate the same query plan, so performance should be the same across both query constructs.
none of the answers worked for me so here is one that i got working. use group bu on col4 while taking max values of other columns
select max(col1) as col1,max(col2) as col2,max(col3) as col3
, col4
from
table1
group by col4
I have the table:
id | date_submitted
1 | 01/01/2017
1 | 01/02/2017
2 | 01/03/2017
2 | 01/04/2017
I'm looking for the correct SQL to select each row, limited to one row per id that has the latest value in date_submitted.
So the SQL should return for the above table:
id | date_submitted
1 | 01/02/2017
2 | 01/04/2017
The query needs to select everything in the row, too.
Thanks for your help.
You can find max date for each id in subquery and join it with the original table to get all the rows with all the columns (assuming there are more columns apart from id and date_submitted) like this:
select t.*
from your_table t
inner join (
select id, max(date_submitted) date_submitted
from your_table
group by id
) t2 on t.id = t2.id
and t.date_submitted = t2.date_submitted;
Note that this query will return multiple rows for an id in case there are multiple rows with date_submitted equals to max date_submitted for that id. If you really want only one row per id, then the solution will be a bit different.
If you just need id and max date use:
select id, max(date_submitted) date_submitted
from your_table
group by id
I'm trying to sort the resutls of a SELECT statement using a custom order like so:
SELECT * FROM table ORDER BY FIELD(id,4,5,6) LIMIT 6
I was expecting to have returned rows with ids: 4,5,6,1,2,3 but instead I'm getting 1,2,3,7,8,9. What am I doing wrong?
As a side note: Prior to running this query, I'm pulling this sort order from the database using a different SELECT with a GROUP_CONCAT function like so:
SELECT group_concat(clickID ORDER BY count DESC separator ',') from table2 WHERE searchphrase='$searchphrase'
This results in the 4,5,6 which is then used in the main query. Is there a faster way to write this all in one statement?
Try it this way
SELECT *
FROM table1
ORDER BY FIELD(id, 4,5,6) > 0 DESC, id
LIMIT 6
Output:
| ID |
|----|
| 4 |
| 5 |
| 6 |
| 1 |
| 2 |
| 3 |
Here is SQLFiddle demo
There is no need of the FIELD function. That will only make things slow.
You just need to properly use the ORDER BY:
SELECT * FROM table
ORDER BY id IN (4,5,6) DESC, id
LIMIT 6
here's how to do it all in one query
SELECT DISTINCT t1.*
FROM table t1
LEFT JOIN table2 ON t1.id = t2.clickID AND t2.searchphrase='$searchphrase'
ORDER BY t2.clickID IS NULL ASC, t1.id ASC
When the LEFT JOIN finds no match, it sets the fields in t2 to NULL in the returned row. This orders by this nullness.
I'm having problems constructing a select query.
I have a table which I have shown in a simplified version below. There are many more columns than those I have shown, but I have ommitied those not relevent to this query.
ID ReceiptNo TransactionType
--------------------------------
1 | 2SJ1532 | SALE
2 | 8UG7825 | SALE
3 | 0619373 | SALE
4 | 8UG7825 | RFND
5 | | TEST
I want to select only those rows that have a transaction type "SALE" where the ReceiptNo for the selected row also appears in a row with transaction type RFND.
So in the above example I would want to select Row 2. Because it has Transaction Type SALE
and its ReceiptNo also appears in a row with transaction type RFND.
I have the following query to select all the SALE type transaction types, but I think I need a subquery to make the select work as descriped above. If anyone could help that would be great.
SELECT * FROM $table_name WHERE RecieptNo IS NOT NULL AND TRIM(RecieptNo) <> '' AND TransactionType = 'SALE'
Try this:
SELECT *
FROM $table_name
WHERE RecieptNo IN(SELECT RecieptNo
FROM tablename
WHERE TransactionType IN('Sale', 'RFND')
GROUP BY RecieptNo
HAVING COUNT( DISTINCT TransactionType) = 2);
This will ensure that the selected RecieptNo have both transaction types Sale, RFND.
SELECT t.*
FROM your_table t
JOIN your_table t2 ON t2.TransactionType = 'RFND' AND t2.ReceiptNo=t.ReceiptNo
GROUP BY t.ID
SELECT *
FROM $table_name X1
WHERE X1.TransactionType = 'SALE'
AND EXISTS (
SELECT X2.ReceiptNo
FROM $table_name X2
WHERE X1.ReceiptNo=X2.ReceiptNo
AND X2.TransactionType = 'RFND'
)
I have a table:
ID int
category int
quantity int
timestamp timestamp
I want to SELECT id="id#" and return a 'position' which is the sum of quantity for each row that has an earlier timestamp in the same category.
Thanks for your pointers!
Try this:
SELECT sum(quantity) FROM TABLE WHERE category='...' AND timestamp < some_timestamp
If you want to select by id:
SELECT sum(quantity) FROM mytable
WHERE category IN (SELECT category FROM mytable WHERE id=some_id)
AND timestamp <= some_timestamp
UPDATE
To use the timestamp from the row itself, you could do something like:
SELECT sum(quantity) FROM mytable
WHERE category IN (SELECT category FROM mytable WHERE id=some_id)
AND timestamp <= (SELECT timestamp FROM mytable WHERE id=some_id)
..or use a self-join as in the Adam's answer (maybe it wasn't an overkill, after all.. :))
UPDATE - Alternate solution
This seems to work fine too..
SELECT t1.id, sum(t2.quantity), t1.timestamp, t1.category
FROM mytable t1 INNER JOIN mytable AS t2 ON t1.category=t2.category
WHERE t1.id=some_id_here AND t2.timestamp <= t1.timestamp;
UPDATE
Changed < into <=, else the quantity for the selected item will not be counted!
You could join your table again with a subquery filtering on your criteria of same category and lesser timestamp.
Here's an example (this was done is sqlite, but it should work in mysql):
select
ID,
sum(foo2.quantity)
from
foo
left join (
select category, quantity, timestamp from foo
) as foo2 on (
foo.category = foo2.category
and foo.timestamp > foo2.timestamp
)
group by
foo.ID
Assuming your data looks like this:
ID|category|quantity|timestamp
1 |foo |2 |2011-01-01
2 |foo |1 |2011-01-02
3 |foo |4 |2011-01-03
4 |bar |4 |2011-01-03
You'll get a result like this:
ID|sum(foo2.quantity)
1 |null
2 |2
3 |3
4 |null
Note: the nulls are because there is no data for those categories prior to the given record.
Note 2: Not sure how performant this will be, but it should get you the data you are looking for.
Update
After re-reading your question, this looks to be a bit overkill... I didn't realize you were passing the id in, either way you could still use this and add a where id = "$id" to restrict it to the id are looking at... hope this helps.
SELECT * FROM table WHERE ID=(SELECT SUM(quantity) WHERE timestamp < some_timestamp AND category = (SELECT category FROM table WHERE ID='given_ID'))
If I understood correctly, this would give you the line which ID is the sum of the quantity of all the lines that have an earlier timestamp and are in the same category as the provided ID.
I didn't test it, but something along those lines should work.
If I understand your question correctly, something like this should do the trick.
$r = mysql_query("SELECT * FROM table WHERE ID='$id'");
$r = mysql_fetch_array($r);
$cat = $r['category'];
$time = $r['timestamp'];
$r = mysql_query("SELECT SUM(quantity) FROM table WHERE category='$cat' AND timestamp <= '$time'");
The first 4 lines retrieve your original id and find the category id and timestamp. Then we run a new query to get all the items in the category older than our id. Because we use <= for the timestamp, it will include our selected id's quantity. If we want to exclude our id's quantity, we would use just <
EDIT: Reading some of the other answers, you could use SUM and skip the while loop... you learn something new every day. Answer changed to reflect this.