group by id in descending order in select statement - mysql

I have MySQL statement where I'm trying to select distinct rows with the latest date.
This is the SQL statement:
SELECT st.seno, tc.pl, tc.sno, st.val1, st.val2, st.date
FROM tc
LEFT JOIN st ON tc.seno = st.seno AND tc.pl = st.pl AND st.seno = 1304239136
WHERE tc.pl = 1
ORDER BY st.date DESC
This is the data returned:
I want to distinct by unique 'tc.sno', therefore I only want the first and third row returned as the middle date is earlier then the top one for the 'sno' 3. The 'sno' could always be different so I do not want to hardcode those numbers. I was trying to use 'GROUP BY' but it just picks the first value of the date, tried using 'HAVING' and combining select statements together but can't seem to get it working. (the val1 and val2 in row 2 could be random it is just a coincidence that they exact in this example)

Related

Should MAX in Group By Retrieve the Whole Row Data

I have a bunch of sql columns to retrieve. This is my SQL statement:
SELECT b.iposx_model_id,
a.mrModel, MAX(a.mrRevision) as mrRevision, a.mrApprovedBy, ...
FROM mydb1.tbl_model_revision a
INNER JOIN mydb2.model_from_revision_process b
ON b.mrModel = a.mrModel
WHERE a.mrType = 1
GROUP BY a.mrModel
ORDER BY b.iposx_model_id ASC
On a certain mrModel column taht I retrieved, these are the data that I'm querying for:
In my query, it states that I should get the data with the Max mrRevision which corresponds to the third row.
However, upon running the sql statement, I got the max mrRevision which is 2, coming from the third row. But the other column data I get came from the 2nd row, an example is mrApprovedBy which is 1035 instead of 10. Why is that happening?
The use group by for only a part of the column not involved in aggegation function is select clause
is depreacted in SQL because where work produce unpredicatble result
In most DB and in the most recent version of mysql this use of group by is not allowed
for obtain the row corresponding to the max value you could use a join on the values that match the right content
SELECT
b.iposx_model_id
, a.mrModel
, t.mrRevision
, a.mrApprovedBy
, ...
FROM mydb1.tbl_model_revision a
JOIN (
select mrModel, MAX(mrRevision) as mrRevision
from mydb1.tbl_model_revision
GROUP BY a.mrModel
) t on a.mrModel = t.mrModel and a.mrRevision = t.mrRevision
JOIN mydb2.model_from_revision_process b ON b.mrModel = a.mrModel
WHERE a.mrType = 1
ORDER BY b.iposx_model_id ASC

Select last two values from two IDs

I would like to select two specific values, the first value is the last inserted row where the ID_SENSOR is 1, and the second value is the last inserted row where the ID_SENSOR is 2.
My Database table:
My Query:
SELECT DATA FROM (SELECT * FROM registovalores WHERE ID_SENSOR = '1' OR ID_SENSOR = '2' ORDER BY ID_SENSOR DESC LIMIT 2) as r ORDER BY TIMESTAMP
My Query is printing the last value just from the ID_SENSOR 1, which it means that I'm only getting the last inserted values, and not the last inserted value from both IDS.
I would like to print my values like this:
ID_SENSOR 1 = 90
ID SENSOR 2 = 800
What do I need to change on my Query?
Thank you.
One method uses a correlated subquery:
SELECT rv.*
FROM registovalores rv
WHERE rv.ID_SENSOR IN (1, 2) AND
rv.TIMESTAMP = (SELECT MAX(rv2.TIMESTAMP)
FROM registovalores rv2
WHERE rv.ID_SENSOR = rv2.ID_SENSOR
);
You have to have two separate queries, one per sensor.
select id_sensor, data
from the_table
where id_sensor = 'sensor_1'
order by timestamp desc -- the latest value is the first to come
limit 1; -- only pick the top (latest) row.
If you want to query for more than one value in a single database roundtrip, consider using union all between several such queries.
Please note that such a query may return one row or zero rows, since data for a particular sensor may not be available yet.

The query gives single row query returns more than one row

I'm trying to show staff_code, staff_name and dept_name for those who have taken one book.
Here's my query:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME,BT.BOOK_CODE
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM,BOOK_TRANSACTIONS BT
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE = (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
It gives the error:
single-row subquery returns more than one row.
How to solve this?
Change = to IN:
WHERE SM.STAFF_CODE IN (SELECT ...)
Because the select returns multiple values, using equals won't work, but IN returns true if any of the values in a list match. The list can be a hard-coded CSV list, or a select with one column like your query is.
That will fix the error, but you also need to remove BOOK_TRANSACTIONS from the table list and remove BOOK_CODE from the select list.
After making these changes, your query would look like this:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE IN (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
I recommend learning the modern (now over 25 year old) JOIN syntax.

How to Display 1 Column sum in other Column

I have a table that has different columns display different values.
I need to add a new column that displays sum of 1 column in each row of other column.
This is what i need to display.
I have written following query but its only displaying 1 in each row of last column.
select inStation.name TapInStation , outStation.name TapOutStation,
count(trx.passengerCount) PassengerCount, sum(trx.amount) Fare,
(select sum(passengerCount) from transactions iTrx
where iTrx.ID = trx.ID) PassengerPercent
from transactions trx
inner join
station inStation on inStation.ID = trx.fromStation
inner join
station outStation on outStation.ID = trx.toStation
GROUP BY
TapInStation, TapOutStation
If you want the total, then remove the correlation clause. This may do what you want:
select inStation.name as TapInStation , outStation.name as TapOutStation,
count(trx.passengerCount) as PassengerCount,
sum(trx.amount) as Fare,
(select sum(passengerCount) from transactions iTrx) as PassengerPercent
I'm not sure why you would called the "total" something like PassengerPercent, but this should return the overall total.
I also suspect that you might want a sum() for the previous expression.

Subquery returns more than 1 row MySQL

Hey so there are these two tables Name and Code and I am trying to make a table with all the Names and match each existing code to the names. Some Names do not have codes so it should display as NULL for those ones. Anyways this is my code:
SELECT company.name,
(SELECT companyclassification.code
FROM insure_prod.companyclassification
WHERE company.OIQ_ID = companyclassification.ussicClassification_StdCompany)
AS USSIC_Code
FROM insure_prod.company
When I try to run this it displays Error Code: 1242 Subquery returns more than 1 row
Thanks in advance
You cannot have a correlated subquery return more than one row. One thing you can do would be to use a LEFT JOIN instead of the correlated subquery:
SELECT c.name,
cc.code AS USSIC_Code
FROM insure_prod.company c
LEFT JOIN insure_prod.companyclassification cc
on c.OIQ_ID = cc.ussicClassification_StdCompany;
This will return a null for the rows that do not exist in the insure_prod.companyclassification table and if you have more than one row that matches you will return multiple rows for each name. If you do not want to return multiple rows for each name, then you will need to alter the query to return one code for each name.
If you want to continue to use your correlated subquery, then you will have to alter the query to limit the result to one row for each name:
SELECT c.name,
(SELECT cc.code
FROM insure_prod.companyclassification cc
WHERE c.OIQ_ID = cc.ussicClassification_StdCompany
ORDER BY cc.ussicClassification_StdCompany
LIMIT 1) AS USSIC_Code
FROM insure_prod.company c
The select companyclassication.code ... query cannot return more than one row. You're trying to return its results into a field context - a field cannot have more than one value in any given row, and you're trying to stuff in 2 or more result records.