How to max(date) and use the in feature in sql ser

2019-05-27 12:02发布

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.

5条回答
Root(大扎)
2楼-- · 2019-05-27 12:24

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;
查看更多
SAY GOODBYE
3楼-- · 2019-05-27 12:34

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');
查看更多
一纸荒年 Trace。
4楼-- · 2019-05-27 12:36

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.

查看更多
Rolldiameter
5楼-- · 2019-05-27 12:41

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
查看更多
叛逆
6楼-- · 2019-05-27 12:47
select id, color, shade, max(date) over() AS m_date from mutable

OVER CLAUSE used IN analyze functions

查看更多
登录 后发表回答