Як вибрати ідентифікатор із максимальною групою дат за категоріями в PostgreSQL?


88

Наприклад, я хотів би вибрати ідентифікатор із максимальною групою дат за категоріями, результат: 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

Чи можу я знати, як це зробити в PostgreSQL?


4
Завжди розумно включати свою версію PostgreSQL.
Ервін Брандштеттер

Відповіді:


141

Це ідеальний варіант використання для DISTINCT ON(спеціальне розширення стандарту Postgres DISTINCT):

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

Обережно з порядком сортування за спаданням. Якщо стовпець може мати значення NULL, ви можете додати NULLS LAST:

DISTINCT ONнайпростіший і швидкий. Детальне пояснення у цій відповіді:

Для великих таблиць розгляньте цей альтернативний підхід:

Оптимізація продуктивності для багатьох рядків за category:


Здається чудово, але ви абсолютно впевнені, що це гарантовано спрацює кожного разу?
Atherion

@Tixel: Абсолютно. Перейдіть за посиланнями, щоб отримати докладнішу інформацію.
Ервін Брандштеттер

21

Спробуйте це:

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

Дивіться цей SQLFiddle


1
Існує ще один варіант використання функції вікна rank ().
Дені де Бернарді,

@ user1735921: Ви отримаєте всі стовпці з таблиці1. Ви можете вибрати, що завгодно.
Хіманшу Янсарі

15

Інший підхід полягає у використанні функції 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;

... хоча я підозрюю, що пропозиція hims056, як правило, буде ефективнішою там, де присутні відповідні індекси.

Третім рішенням є:

SELECT
  id
FROM (
  SELECT
    id,
    row_number() OVER (PARTITION BY "category" ORDER BY "date" DESC) AS rownum
  FROM Table1
) x
WHERE rownum = 1;

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.