SQL select only one item which meets condition - sql

I have a very narrow table: DATA, ID, LAT, LNG, TIME.
(https://gyazo.com/52b268c00963ed12ba85c6765f40bf63)
And I want to select the newest data for each different ID. I was using query like
SELECT *
FROM name_of_table
WHERE TIME > my_given_time;
but it selects TOTALLY all datas and not only data for each different id which meets the condition.
Could somebody please help me write the query?
Thank you for any help. :)
EDIT
The final look of my working query looks like:
SELECT * FROM (SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY TIME DESC) AS ROWNUMBER, * FROM my_table) WHERE ROWNUMBER = 1) WHERE TIME > my_time;
Thanks everyone for help

How about something like this
SELECT ID, DATA
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY TIME DESC) AS ROWNUMBER, ID, DATA
FROM name_of_table)
WHERE ROWNUMBER = 1;
For these dummy records
INSERT INTO name_of_table (ID, TIME, DATA) VALUES('test',1230,16);
INSERT INTO name_of_table (ID, TIME, DATA) VALUES('test2',1235,10);
INSERT INTO name_of_table (ID, TIME, DATA) VALUES('test',1234,20);
the query returns the data value for the largest timestamp for each ID
ID DATA
----- ----
test 20
test2 10

I would do something like this:
SELECT tt.* FROM tblTest tt
WHERE _ID IN (
SELECT TOP 1 _ID FROM tblTest WHERE ID = tt.ID ORDER BY TIME DESC
)
Assuming _ID that i found in your linked picture is a unique identifier for each individual row

Try this:
SELECT a.*
FROM `sometable` a
JOIN (SELECT MAX(TIME) AS `max_time`,`ID` FROM `sometable` group by `ID`) b
ON b.`ID` = a.`ID` AND a.`TIME` = b.`max_time`;

Related

SQL Server Group By with Max on Date field

I hope i can explain the issue i'm having and hopefully so can point me in the same direction.
I'm trying to do a group by (Email Address) on a subset of data, then i'm using a max() on a date field but because of different values in other fields its bring back more rows then require.
I would just like to return the max record per email address and return the fields that are on the same row that are on the max record.
Not sure how i can write this query?
This is a task for ROW_NUMBER:
select *
from
(
select t.*,
-- assign sequential number starting with 1 for the maximum date
row_number() over (partiton by email_address order by datecol desc) as rn
from tab
) as dt
where rn = 1 -- only return the latest row
You can write this query using row_number():
select t.*
from (select t.*,
row_number() over (partition by emailaddress order by date desc) as seqnum
from t
) t
where seqnum = 1;
How about something like this?
select a.*
from baseTable as a
inner join
(select Email,
Max(EmailDate) as EmailDate
from baseTable
group by Email) as b
on a.Email = b.Email
and a.EmailDate = b.EmailDate

SQL Server: INSERT INTO SELECT MAX

I want to insert multi rows from another table. The problem is that I want to get the Max + 1 before I insert. Note that I know I should use Identify etc... However, I have this complex scenario of offline database synchronization across nodes...
INSERT INTO Purchase_Deliveries_Items
(ID,Item_ID)
SELECT
(SELECT
MAX(ID)+1 -- same MAX ID for all (the problem)
FROM
Purchase_Deliveries_Items),
Item_ID,
FROM
Purchase_Orders_Items
WHERE
PurchaseOrder_ID = 1
You can get a newid based on the max existing id with the help of ROW_NUMBER
INSERT INTO Purchase_Deliveries_Items (
ID,
Item_ID
)
SELECT
ROW_NUMBER() OVER (
ORDER BY
Item_ID
) + (SELECT MAX(ID)
FROM Purchase_Deliveries_Items) newID,
Item_ID,
FROM Purchase_Orders_Items
WHERE
PurchaseOrder_ID = 1
Seems like you want to do a kind of sequence, use a ROW_NUMBER:
INSERT INTO Purchase_Deliveries_Items
(ID,Item_ID)
SELECT (
SELECT MAX(ID) -- same MAX ID for all
FROM Purchase_Deliveries_Items
) + ROW_NUMBER() OVER (ORDER BY any_column),
Item_ID,
FROM Purchase_Orders_Items
WHERE PurchaseOrder_ID = 1

get the field with longest string for same id value

I have to get the row with longest string value for same id fields.
create table test(
id number,
test_data varchar2(20)
);
insert all
into test values (1,'aaa')
into test values (1,'a')
into test values (1,'abxw')
into test values (2,'aaa')
into test values (2,'tris')
select * from dual;
my desired output is
1 abxw --longest string
2 tris
how can I get the required output?? I am not getting any idea.
guys what about using cursor. can we use cursor for this purpose?? Does anyone have any idea? Is it possible??
Thank You.
I like using partition for these kind of queries:
select id,test_data from (
select
id, test_data,
row_number() over( partition by id order by length(test_data) desc) as rnum
from
test
) where rnum=1
http://www.sqlfiddle.com/#!4/66d4c/20
Of course, the nice thing about this is that if you decide that you want another tiebreak (e.g., alphabetically), you just need to add that to your order by clause. Which, by the way is not a bad idea, that way your result set will not be non-deterministic.
You can try this query. It will return multiple results if multiple strings have the longest length per id:
select
t1.id, t1.test_data
from
test t1
join
(select id, max(length(test_data)) as len from test group by id) t2
on t1.id = t2.id and length(t1.test_data) = t2.len
Demo: http://www.sqlfiddle.com/#!4/66d4c/6
I think the analytic (window) function RANK() is the best way to accomplish this.
SELECT id, test_data FROM (
SELECT id, test_data
, RANK() OVER ( PARTITION BY id ORDER BY LENGTH(test_data) DESC ) AS the_rank
FROM test
) WHERE the_rank = 1
If you want only one record, then you can do the following:
SELECT id, test_data FROM (
SELECT id, test_data
, RANK() OVER ( PARTITION BY id ORDER BY LENGTH(test_data) DESC ) AS the_rank
FROM test
ORDER BY the_rank
) WHERE rownum = 1

Getting the smaller index for each duplicate in SQL

Let's say I have a table with two columns, one column for the ID and another for a Name. All the names in this table appear more than once.
How can I get all the IDs in the table excluding the smallest IDs for each Name?
In SQL Server 2005+ you could go like this:
SELECT ID FROM atable
EXCEPT
SELECT MIN(ID) FROM atable GROUP BY Name
I would use a CTE (Common Table Expression) using the ROW_NUMBER() ranking function for that:
;WITH GroupedNames AS
(
SELECT ID, Name,
ROW_NUMBER() OVER(PARTITION BY Name ORDER BY ID) AS 'RowNum'
FROM
dbo.YourTable
)
SELECT *
FROM GroupedNames
This will "partition" your data by means, e.g. create groups by name, and each group will get consecutive numbers starting at 1. This way, you can easily select everything except the entry (ID, Name) with the smallest ID with this:
.....
SELECT *
FROM GroupedNames
WHERE RowNum > 1
and if you need to, you can even use this construct to actually delete all those names with a row number bigger than 1 (all the "duplicates"):
;WITH GroupedNames AS
(
SELECT ID, Name,
ROW_NUMBER() OVER(PARTITION BY Name ORDER BY ID) AS 'RowNum'
FROM
dbo.YourTable
)
DELETE FROM GroupedNames
WHERE RowNum > 1
Maybe this would work?
SELECT id FROM table WHERE id NOT IN (SELECT MIN(id) FROM table GROUP BY name)
SELECT DISTINCT b.id
FROM yourTable a
JOIN yourTable b
ON a.name = b.name
AND a.id < b.id

SQL Group by & Max

I have a following data in a table:
id name alarmId alarmUnit alarmLevel
1 test voltage psu warning
2 test voltage psu ceasing
3 test voltage psu warning
4 test temp rcc warning
5 test temp rcc ceasing
I'd like to show only the most recent information about every colums group (alarmId,alarmUnit), so the result should look like this:
3 test voltage psu warning
5 test temp rcc ceasing
I've tried so far:
SELECT MAX(id) as id,name,alarmId,alarmUnit,alarmLevel GROUP BY alarmId,alarmUnit;
Selected IDs seem to be fine but selected rows aren't corresponding to them. Could you help me?
In Oracle, SQL Server 2005+ and PostgreSQL 8.4:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY alarmId, alarmUnit ORDER BY id DESC) AS rn
FROM mytable
) q
WHERE rn = 1
In MySQL:
SELECT mi.*
FROM (
SELECT alarmId, alarmUnit, MAX(id) AS mid
FROM mytable
GROUP BY
alarmId, alarmUnit
) mo
JOIN mytable mi
ON mi.id = mo.mid
In PostgreSQL 8.3 and below:
SELECT DISTINCT ON (alarmId, alarmUnit) *
FROM mytable
ORDER BY
alarmId, alarmUnit, id DESC
If you want to get the row of the max, you'll probably need a sub-query. Something like:
SELECT *
FROM YourTable
WHERE id IN (
SELECT MAX(id) FROM YourTable GROUP BY alarmId, alarmUnit
)
Try:
SELECT * FROM table WHERE id IN
(SELECT MAX(id) FROM table GROUP BY alarmId, alarmUnit)
Maybe try something like the following:
SELECT id,name,alarmId,alarmUnit,alarmLevel
FROM table
WHERE id IN (SELECT Max(id) FROM table GROUP BY alarmId, alarmUnit)
You may have to include alarmId and alarmUnit in the sub query select.
select id, name, alarmID, alarmUnit, alarmLevel
from (select max(id) as id
from table
group by alarmID, alarmUnit) maxID
inner join table
on table.id = maxID.id