Jak wybrać id z max date group według kategorii w PostgreSQL?

Dla przykładu chciałbym wybrać id z max date group by category, wynik to: 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

Czy Mogę wiedzieć jak to zrobić w PostgreSQL?

Author: Erwin Brandstetter, 2013-06-04

4 answers

Jest to idealny przypadek użycia dla DISTINCT ON (Postgres specific extension of standard DISTINCT):

SELECT DISTINCT ON (category)
       id  -- , category, date -- add any other column (expression) from the same row
FROM   tbl
ORDER  BY category, "date" DESC;

Ostrożnie z malejącym porządkiem sortowania. Jeśli kolumna może być NULL, możesz dodać NULLS LAST:

DISTINCT ON jest najprostszy i szybki. Szczegółowe wyjaśnienie w tej powiązanej odpowiedzi:

Do dużych stołów rozważmy to alternatywne podejście:

Optymalizacja wydajności dla wielu wierszy na category:

 90
Author: Erwin Brandstetter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-05 11:31:40

Spróbuj tego:

SELECT * 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

Zobacz ten SQLFiddle

 15
Author: hims056,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-04 09:25:24

Innym podejściem jest użycie funkcji okna first_value: http://sqlfiddle.com/#! 12 / 7a145/14

SELECT DISTINCT
  first_value("id") OVER (PARTITION BY "category" ORDER BY "date" DESC) 
FROM Table1
ORDER BY 1;

... chociaż podejrzewam, że sugestia hims056 Zazwyczaj będzie działać lepiej tam, gdzie obecne są odpowiednie indeksy.

Trzecie rozwiązanie to:

SELECT
  id
FROM (
  SELECT
    id,
    row_number() OVER (PARTITION BY "category" ORDER BY "date" DESC) AS rownum
  FROM Table1
) x
WHERE rownum = 1;
 10
Author: Craig Ringer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-04 12:29:17

SELECT id FROM TBL GROUP BY cat HAVING MAX (date)

 -2
Author: Unmerciful,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-27 09:56:59