SQL Select the Columnid with a max column group by one column - sql

I think this question is already answered but it didn't satisfy my question.
I'd like to select the id/s of the names group by the latest date value (MAX) in my table. Using a group by column Name and group by column Date, I must get the ID, Name, Date.
Here is my table
ID Name Date
---------------------------------------
1 Brent 2012-02-17
2 Ash 2012-08-02
3 Brent 2012-08-15
4 Harold 2012-09-30
5 Margaret 2012-10-10
6 Ash 2012-12-01
7 Harold 2013-02-14
8 Ash 2012-01-01
9 Brent 2013-05-11
Output must be:
ID Name Date
---------------------------------------
5 Margaret 2012-10-10
6 Ash 2012-12-01
7 Harold 2013-02-14
9 Brent 2013-05-11
I try this statement:
SELECT
[ID], [Name], MAX([Date]) as [Date]
FROM
[SampleTable]
GROUP BY
[Name]
But I get this error:
Column 'ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

you can use Window Function such as ROW_NUMBER()
SELECT a.ID, a.Name, a.Date
FROM
(
SELECT ID, Name, Date,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DATE DESC) rn
FROM TableName
) a
WHERE a.rn = 1
if ID and Name is the same for every group, you can simply add Name in the GROUP BY clause.
GROUP BY ID, Name

Related

Find Column With Max on Other Column Grouping By Another Column

I have a table like this:
Id - ItemId - Price - SalesId - Date
1 12 99.99924 21899234 2025-01-01 00:00:00.000000
2 123 12.34567 348923 2021-01-01 00:00:00.000000
3 1234 1234.5 3321234 2022-01-01 00:00:00.000000
4 12345 3.3246 2154234 2023-01-01 00:00:00.000000
5 1234 451.234 3423 2020-02-01 00:00:00.000000
6 12345 0.989 71112357 2020-09-15 20:20.10.000000
7 123 3435.3 71112357 2020-09-14 20:10:12.000000
I am trying to find the Price of an Item with latest Date. For example, if we tried to find ItemId = 1234, the one with the latest date is this 2022-01-01 00:00:00.000000 that has Id = 3, it has the price of 1234.5. That's what I'm trying to find by this query, the price of this item.
I am a beginner to SQL and tried the following query, but it gives me this error:
select "ItemId",
max("Date"),
"Price"
from "Products"
group by "ItemId"
[42803] ERROR: column "Products.Price" must appear in the GROUP BY clause or be used in an aggregate function
I appreciate any help here. Thank you!
In Postgres, you can use distinct on:
select distinct on ("ItemId") p.*
from "Products" p
order by "ItemId", "Date" desc;
Note: If you are learning SQL, don't use double quotes for string and column names.
You can try using row_number()
select * from
(
select ItemId,Date,Price,row_number() over(partition by itemid order by date desc) as rn
from Products
)A where rn=1

find the youngest student from date

I have the below table:
name id DOB marks
rk 2 2006-02-03 00:00:00.000 30
mk 3 2006-07-07 00:00:00.000 30
pk 4 2006-04-09 00:00:00.000 30
sk 5 2006-05-03 00:00:00.000 30
fk 6 2006-08-09 00:00:00.000 30
nk 7 2007-08-06 00:00:00.000 30
How can I find the youngest student?
You can order your table by descending date of birth and then filter the first result only, which in SQL Server can be done with
select top 1 *
from yourTable
order by DOB desc
Looks like you just need the latest date of birth (assuming DOB is date of birth):
select max(dob) from yourtable
Then your query would be:
select name as youngestStudent, dob as dateOfBirth
from yourtable
where dob = (select max(dob) from yourtable)
It's simple. According to your given data "nk" is the youngest student, so you can use the following query :
select * from yourtable
where dob = (select max(dob) from yourtable)

SQL: Take maximum value, but if a field is missing for a particular ID, ignore all values

This is somewhat difficult to explain...(this is using SQL Assistant for Teradata, which I'm not overly familiar with).
ID creation_date completion_date Difference
123 5/9/2016 5/16/2016 7
123 5/14/2016 5/16/2016 2
456 4/26/2016 4/30/2016 4
456 (null) 4/30/2016 (null)
789 3/25/2016 3/31/2016 6
789 3/1/2016 3/31/2016 30
An ID may have more than one creation_date, but it will always have the same completion_date. If the creation_date is populated for all records for an ID, I want to return the record with the most recent creation_date. However, if ANY creation_date for a given ID is missing, I want to ignore all records associated with this ID.
Given the data above, I would want to return:
ID creation_date completion_date Difference
123 5/14/2016 5/16/2016 2
789 3/25/2016 3/31/2016 6
No records are returned for 456 because the second record has a missing creation_date. The record with the most recent creation_date is returned for 123 and 789.
Any help would be greatly appreciated. Thanks!
Depending on your database, here's one option using row_number to get the max date per group. You can then filter those results with not exists to check against null values:
select *
from (
select *,
row_number() over (partition by id order by creation_date desc) rn
from yourtable
) t
where rn = 1 and not exists (
select 1
from yourtable t2
where t2.creationdate is null and t.id = t2.id
)
row_number is a window function that is supported in many databases. mysql doesn't but you can achieve the same result using user-defined variables.
Here is a more generic version using conditional aggregation:
select t.*
from yourtable t
join (select id, max(creation_date) max_creation_date
from yourtable
group by id
having count(case when creation_date is null then 1 end) = 0
) t2 on t.id = t2.id and t.creation_date = t2.max_creation_date
SQL Fiddle Demo

Getting a row with two group by constraints

I have a table
TIMESTAMP ID Name
5/30/2016 11:45 1 Ben
5/30/2016 11:45 2 Ben
5/30/2016 23:15 2 Ben
5/30/2016 7:30 1 Peter
5/30/2016 6:05 1 Peter
5/30/2016 14:40 2 May
5/30/2016 1:05 1 May
Now, I need to get the MIN timestamp for each distinct Name.
Then if there are more than one MIN entry, choose the one with the MAX ID.
So the result should be
TIMESTAMP ID Name
5/30/2016 11:45 2 Ben
5/30/2016 6:05 1 Peter
5/30/2016 1:05 1 May
I tried using the query below:
SELECT MIN(TIMESTAMP),NAME FROM TBLSAMPLE WHERE TIMESTAMP BETWEEN TO_DATE('5/30/2016', 'MM/DD/YYYY' ) AND TO_DATE('5/30/2016', 'MM/DD/YYYY' ) + 1
GROUP BY NAME
and I could get the minimum time. But once I add in MAX(ID) the result return an entry that does not match any of the rows.
Your help are really appreciated.
You can do this with row_number():
select t.*
from (select t.*,
row_number() over (partition by name order by timestamp asc, id desc) as seqnum
from tblsample t
) t
where seqnum = 1;
Your question doesn't specify a condition on the dates. But if you want to add a where clause, then add it to the subquery.

Renumbering rows in SQL Server

I'm kinda new into the SQL Server and I'm having the following question: is there any possibility to renumber the rows in a column?
For ex:
id date name
1 2016-01-02 John
2 2016-01-02 Jack
3 2016-01-02 John
4 2016-01-02 John
5 2016-01-03 Jack
6 2016-01-03 Jack
7 2016-01-04 John
8 2016-01-03 Jack
9 2016-01-02 John
10 2016-01-04 Jack
I would like that all "Johns" to start with id 1 and go on (2, 3, 4 etc) and all "Jacks" have the following number when "John" is done (5, 6, 7 etc). Thanks!
I hope this helps..
declare #t table (id int ,[date] date,name varchar(20))
insert into #t
( id, date, name )
values (1,'2016-01-02','John')
,(2,'2016-01-02','Jack')
,(3,'2016-01-02','John')
,(4,'2016-01-02','John')
,(5,'2016-01-03','Jack')
,(6,'2016-01-03','Jack')
,(7,'2016-01-04','John')
,(8,'2016-01-03','Jack')
,(9,'2016-01-02','John')
,(10,'2016-01-04','Jack')
select
row_number() over(order by name,[date]) as ID,
date ,
name
from
#t
order by name
The id should just be an internal identifier you use for joins etc - I wouldn't change it. But you could query such a numbering using a window function:
SELECT ROW_NUMBER() OVER (ORDER BY CASE name WHEN 'John' THE 1 ELSE 2 END) AS rn,
date,
name
FROM mytable
Instead of renumbering the id column, you can use ROW_NUMBER window function to renumber the rows as per your requirement. for e.g.:
SELECT ROW_NUMBER() OVER(PARTITION BY name ORDER BY date) as rowid,date,name
FROM tablename