可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a table such as this
id color shade date
--- ---- ----- -----
1 red dark 01/01/1990
2 red light 09/16/2013
3 green light 08/15/2010
4 green dark 09/18/2012
5 maroon dark 08/20/2013
6 white dark 08/31/2013
7 white light 08/30/2012
8 purple light 08/20/2010
I wanted entries for each color with the latest date. So I tried doing:
select id, color, shade, max(date) from mytable;
This didn't work and gave me error:
is invalid in the select list because it is not contained in either an aggregate
function or the GROUP BY clause.
Alright, so I added it in the Group By
as suggested by the error
select id, color, shade, max(date) from mutable
Group by id, color, shade
This gave me the desired results.
Question
Now, I wanted the same query as above repeated only for certain colors. For example I only wanted to see red and green ones.
So I did:
select id, color, shade, max(date) from mutable
Where color in ('red', 'green')
Group by id, color, shade;
However, this does not give me the correct number of results because I guess they are being grouped by shade
.
What is the best way to fetch my desired results? Basically I want max date
out of the two instances of same thing and further out of the table only want certain colors.
回答1:
In standard SQL any of the following queries solve the issue:
Option 1
SELECT t1.* FROM t t1
LEFT JOIN t t2
ON t1.color = t2.color AND t1.shade = t2.shade AND t1.date < t2.date
WHERE t2.date IS NULL
Option 2
SELECT t1.* FROM t t1
JOIN (
SELECT color, shade, max(date) date FROM t
GROUP BY color, shade
) t2
ON t1.color = t2.color AND t1.shade = t2.shade AND t1.date = t2.date
In your example data, all the result should be returned, so it doesn't make much sense to operate on it. I've slightly changed it into this:
| ID | COLOR | SHADE | DATE |
|----|-------|-------|------------|
| 1 | red | dark | 1990-01-01 |
| 2 | red | dark | 2013-09-16 |
| 3 | green | light | 2010-08-15 |
| 4 | green | dark | 2012-09-18 |
| 5 | green | dark | 2013-08-20 |
| 6 | white | dark | 2013-08-31 |
| 7 | white | light | 2012-08-30 |
| 8 | white | light | 2010-08-20 |
The output of the queries would be:
| ID | COLOR | SHADE | DATE |
|----|-------|-------|------------|
| 2 | red | dark | 2013-09-16 |
| 3 | green | light | 2010-08-15 |
| 5 | green | dark | 2013-08-20 |
| 6 | white | dark | 2013-08-31 |
| 7 | white | light | 2012-08-30 |
Make sure you apply the appropriate orderings.
Fiddle here.
回答2:
Try this
SELECT t1.* FROM t t1
JOIN
(
SELECT color, MAX([date]) [date] FROM t
WHERE color IN ('red', 'green')
GROUP BY color
) t2
ON t1.color = t2.color AND t1.date = t2.date
ORDER BY ID
OUTPUT
id color shade date
2 red light 2013-09-16
5 green dark 2013-08-20
OR
SELECT id, color, shade, [date]
FROM
(
SELECT *,
row_number() OVER (PARTITION BY color ORDER BY [date] DESC) AS sno
FROM t
WHERE color IN ('red', 'green')
) tt
WHERE sno = 1
ORDER BY ID
OUTPUT
id color shade date
2 red light 2013-09-16
5 green dark 2013-08-20
OR
SELECT id, color, shade, [date]
FROM
(
SELECT *,
MAX([date]) OVER (PARTITION BY color) AS maxdate
FROM t
WHERE color IN ('red', 'green')
) tt
WHERE [date] = maxdate
ORDER BY ID
OUTPUT
id color shade date
2 red light 2013-09-16
5 green dark 2013-08-20
回答3:
select id, color, shade, max(date) over() AS m_date from mutable
OVER CLAUSE used IN analyze functions
回答4:
A simple way to think about this is by first creating a query that gives you the latest date for each colour:
select color, max([date]) as maxdate
from mytable
group by color;
Then by joining this query with a simple select query that just retrieves all rows from your original table:
select t.[id], t.color, t.shade, sq.maxdate
from mytable as t
inner join (
select color, max([date]) as maxdate
from mytable
group by color
) as sq
on (t.color = sq.color);
Then, to restrict the results to only certain colours, just add on your where
clause at the end of the query:
where color in ('red', 'green');
回答5:
The easiest way to do this is with window/ranking functions. Here is an example with row_number()
:
select id, color, shade, "date"
from (select t.*,
row_number() over (partition by color order by "date" desc) as seqnum
from mytable
) t
where seqnum = 1;