Select newest records that have distinct Name column - sql

I did search around and I found this
SQL selecting rows by most recent date with two unique columns
Which is so close to what I want but I can't seem to make it work.
I get an error Column 'ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I want the newest row by date for each Distinct Name
Select ID,Name,Price,Date
From table
Group By Name
Order By Date ASC
Here is an example of what I want
Table
ID
Name
Price
Date
0
A
10
2012-05-03
1
B
9
2012-05-02
2
A
8
2012-05-04
3
C
10
2012-05-03
4
B
8
2012-05-01
desired result
ID
Name
Price
Date
2
A
8
2012-05-04
3
C
10
2012-05-03
1
B
9
2012-05-02
I am using Microsoft SQL Server 2008

Select ID,Name, Price,Date
From temp t1
where date = (select max(date) from temp where t1.name =temp.name)
order by date desc
Here is a SQL Fiddle with a demo of the above
Or as Conrad points out you can use an INNER JOIN (another SQL Fiddle with a demo) :
SELECT t1.ID, t1.Name, t1.Price, t1.Date
FROM temp t1
INNER JOIN
(
SELECT Max(date) date, name
FROM temp
GROUP BY name
) AS t2
ON t1.name = t2.name
AND t1.date = t2.date
ORDER BY date DESC

There a couple ways to do this. This one uses ROW_NUMBER. Just partition by Name and then order by what you want to put the values you want in the first position.
WITH cte
AS (SELECT Row_number() OVER (partition BY NAME ORDER BY date DESC) RN,
id,
name,
price,
date
FROM table1)
SELECT id,
name,
price,
date
FROM cte
WHERE rn = 1
DEMO
Note you should probably add ID (partition BY NAME ORDER BY date DESC, ID DESC) in your actual query as a tie-breaker for date

select * from (
Select
ID, Name, Price, Date,
Rank() over (partition by Name order by Date) RankOrder
From table
) T
where RankOrder = 1

I have found another memory efficient way (but probably crude way)that has worked for me in postgress. Order the query by the date desc, then select the first record of each distinct field.
SELECT distinct on (Name) ID, Price, Date from
table
order by Date desc

Use Distinct instead of Group By
Select Distinct ID,Name,Price,Date
From table
Order By Date ASC
http://technet.microsoft.com/en-us/library/ms187831.aspx

Related

Select multiple max values after GROUP BY query

Suppose I have a table look like this:
date ID income
0 9/1 C 10.40
1 9/3 A 33.90
2 9/3 B 29.10
3 9/4 C 19.30
4 9/4 B 17.80
5 9/5 B 9.55
6 9/5 C 11.10
7 9/5 A 13.10
8 9/7 A 29.10
9 9/7 B 29.10
I want to find out the ID who made the most income for each date. The most intuitive approach would be writing
SELECT ID, MAX(income) FROM table GROUP BY date
But there are two IDs who made the same MAX income on 9/7, I want to retain all ties on the same date, by using that query I will ignore one ID on 9/7, and 29.1 appears on 9/3 and 9/7, any other approach?
A join based approach doesn't have this problem, and would retain all records tied for the max income on a given date.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT date, MAX(income) AS max_income
FROM yourTable
GROUP BY date
) t2
ON t1.date = t2.date AND t1.income = t2.max_income
ORDER BY
t1.date;
The way the above query works is to join the complete original table to a subquery which finds, for each date, the maximum income value. This has the effect of filtering off any record which did not have the max income on a given date. Pay close attention to the join condition, which has two components, the date, and the income.
If your database supports analytic function, we can also use RANK here:
SELECT date, ID, income
FROM
(
SELECT t.*, RANK() OVER (PARTITION BY date ORDER BY income DESC) rnk
FROM yourTable t
) t
WHERE rnk = 1
ORDER BY date;
one approach can be like below
with cte1
(
Select t1.*
FROM yourTable t1
INNER JOIN
(
SELECT date, MAX(income) AS max_income
FROM yourTable
GROUP BY date
) t2
ON t1.date = t2.date AND t1.income = t2.max_income
) select min(ID) as ID, date,income from cte1
group by date,income
As you not mentioned which id you need in case of two ID's(when income is same on a particular date) so i took minimum id among them when two id's income is same on a particular date But at the same time you may use max() function also
Try below using subquery and as you've tie for one date so take minimum ID which'll give you one id from date 9/7
select date,min(ID),income
from
(SELECT t1.date, t1.ID,t1.income
FROM tablename t1
INNER JOIN
(
SELECT date, MAX(income) AS mincome
FROM yourTable
GROUP BY date
) t2 ON t1.date = t2.date AND t1.income = t2.mincome
)X group by date,income

SQL - Filtering by closest date [duplicate]

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 4 years ago.
Let's say I have a table:
SELECT * FROM table;
Ric Charge Date
VOD.L 2 20180601
VOD.L 5 20181002
VOD.L 4.5 20180212
RBS.L 3 20180504
RBS.L 6 20180708
How could I filter, by date, such that it will return ONLY the most recent charge
E.g.
Ric Charge Date
VOD.L 4.5 20180212
RBS.L 6 20180708
I would prefer simple top 1
select top 1 * from t order by date desc
As you edit question, you can use co-related subquery byt your sample output is wrong
select * from t
where t.date in (select max(t1.date) from t t1
where t1.Ric=t.Ric
)
Demo
Ric Charge Date
VOD.L 5.000 02/10/2018 00:00:00
RBS.L 6.000 08/07/2018 00:00:
Something like
SELECT * FROM table WHERE date = (SELECT MAX(date) FROM table)
does what you ask(in multiple DB too)..
Date is a keyword in SQL and makes for a poor column name. If you can, change it now. If you can't, you might need to quote it according to the database you have
Order by the date and then use LIMIT 1 to only get one record.
SELECT *
FROM table
ORDER BY date DESC
LIMIT 1;
I would use row_number() with ties clause :
select top (1) with ties t.*
from table t
order by row_number() over (partition by ric order by date desc);
If the date has ties then you can use dense_rank() instead of row_number().
A self left join with an inequality would work:
SELECT t1.*
FROM
table t1
LEFT JOIN table t2 ON
t1.date < t2.date
WHERE
t2.date IS NULL
GROUP BY
t1.Ric
;
You can use a window function such as ROW_NUMBER to create a windowed order number, then you can extract only the record with row number = 1 (the latest date):
declare #tmp table (Ric varchar(50), Charge numeric(10,3), [Date] Date)
insert into #tmp values
('VOD.L', 2 , '20180601')
,('VOD.L', 5 , '20181002')
,('VOD.L', 4.5, '20180212')
,('RBS.L', 3 , '20180504')
,('RBS.L', 6 , '20180708')
select t.Ric, t.Charge, t.[Date]
from (
select ric,
Charge,
row_number() over (partition by ric order by [Date] desc) as rn,
[Date]
from #tmp
) t where rn = 1
Result:
From your question it is not clear what sholud happen when there are more rows with the same Ric/date values
As an alternative, you could use not exists.
SELECT *
FROM TableA AS A
WHERE NOT EXISTS ( SELECT * FROM TableA AS A2
WHERE A.Ric = A2.Ric
AND A2.Date > A.Date )

Group by with MIN value in same query while presnting all other columns

I have a view called a with this data:
ID tDate name task val
23 2015-06-14
23 2015-06-25
126 2015-06-18
126 2015-06-22
126 2015-06-24
ID is integer and tDate is timestamp.
Basically I want to get for each ID the min value of tDate and present this row.
meaning:
ID tDate name task val
23 2015-06-14
126 2015-06-18
I wrote this query:
select ID, min(tDate)
from a
group by ID
order by ID
This is working BUT it doesn't allow me to present all other columns of a
for example if I do:
select ID, min(tDate), name
from a
group by ID
order by ID
it says that name must be under group by. So I wrote this query:
select ID, MIN(tDate), name, task, val , ....
from a
group by ID, name, task, val , ....
order by ID
And this one doesn't work. it gives false results.
How do I solve it?
Postgres has the very convenient distinct on for this type of problem:
select distinct on (id) a.*
from a
order by id, tdate;
This will return one row for each id. The row is the first one determined by the ordering defined in the order by clause.
Do a join from the one table to a sub-query table on just the ID / Min Date
select
YT.ID,
YT.tDate as OriginalDate,
PQ.MinDate,
YT.name,
YT.task,
YT.val
from
YourTable YT
JOIN ( select ID, min( tdate ) as MinDate
from YourTable
group by ID ) as PQ
on YT.ID = PQ.ID
AND YT.tDate = PQ.MinDate
order by
ID
Try something like this:
select a.id, a.tdate , .... from a
join (select id, min(tdate) min_date
from a
group by ID
) b
on a.id=b.id and a.tdate = b.min_date
order by a.id

How to select id with max date group by category in PostgreSQL?

For an example, I would like to select id with max date group by category,
the result is: 7, 2, 6
id category date
1 a 2013-01-01
2 b 2013-01-03
3 c 2013-01-02
4 a 2013-01-02
5 b 2013-01-02
6 c 2013-01-03
7 a 2013-01-03
8 b 2013-01-01
9 c 2013-01-01
May I know how to do this in PostgreSQL?
This is a perfect use-case for DISTINCT ON - a Postgres specific extension of the standard DISTINCT:
SELECT DISTINCT ON (category)
id -- , category, date -- any other column (expression) from the same row
FROM tbl
ORDER BY category, date DESC;
Careful with descending sort order. If the column can be NULL, you may want to add NULLS LAST:
Sort by column ASC, but NULL values first?
DISTINCT ON is simple and fast. Detailed explanation in this related answer:
Select first row in each GROUP BY group?
For big tables with many rows per category consider an alternative approach:
Optimize GROUP BY query to retrieve latest row per user
Optimize groupwise maximum query
Try this one:
SELECT t1.* FROM Table1 t1
JOIN
(
SELECT category, MAX(date) AS MAXDATE
FROM Table1
GROUP BY category
) t2
ON T1.category = t2.category
AND t1.date = t2.MAXDATE
See this SQLFiddle
Another approach is to use the first_value window function: http://sqlfiddle.com/#!12/7a145/14
SELECT DISTINCT
first_value("id") OVER (PARTITION BY "category" ORDER BY "date" DESC)
FROM Table1
ORDER BY 1;
... though I suspect hims056's suggestion will typically perform better where appropriate indexes are present.
A third solution is:
SELECT
id
FROM (
SELECT
id,
row_number() OVER (PARTITION BY "category" ORDER BY "date" DESC) AS rownum
FROM Table1
) x
WHERE rownum = 1;

group rows in plain sql

I have a Table with columns Date and Number, like so:
date Number
1-1-2012 1
1-2-2012 1
1-3-2012 2
1-4-2012 1
I want to make a sql query that groups the rows with the same Number and take the minimum date. The grouping only may occur when the value iof Number is the same as previous / next row. So the rsult is
date Number
1-1-2012 1
1-3-2012 2
1-4-2012 1
try this:
WITH CTE AS(
SELECT * ,ROW_NUMBER() OVER (ORDER BY [DATE] ) -
ROW_NUMBER() OVER (PARTITION BY NUMBER ORDER BY [DATE] ) AS ROW_NUM
FROM TABLE1)
SELECT NUMBER,MIN(DATE) AS DATE
FROM CTE
GROUP BY ROW_NUM,NUMBER
ORDER BY DATE
SQL fiddle demo
SELECT Number, MIN(date)
FROM table
GROUP BY Number
ORDER BY Number
since you requirement is a bit more specific, how about this? I have not checked it myself, but something that might work, considering you requirement..
SELECT date, Number FROM (
SELECT Number,
(SELECT MIN(date) FROM #table t2 WHERE t1.date <> t2.date AND t1.Number = t2.Number) AS date
FROM table t1
) AS a
GROUP BY number, date