Как выбрать в SQL на основе значения из того же столбца таблицы? - PullRequest
0 голосов
/ 12 января 2019

У меня есть следующая таблица

| id | date       | team |
|----|------------|------|
| 1  | 2019-01-05 | A    |
| 2  | 2019-01-05 | A    |
| 3  | 2019-01-01 | A    |
| 4  | 2019-01-04 | B    |
| 5  | 2019-01-01 | B    |

Как я могу запросить таблицу, чтобы получить самые последние значения для команд?

Например, результатом для вышеприведенной таблицы будет ids 1,2,4.

Ответы [ 4 ]

0 голосов
/ 13 января 2019

Оконная функция - лучшее решение для вас.

select id
from (
  select team, id, rank() over (partition by team order by date desc) as row_num
  from table
) t
where row_num = 1

Этот запрос вернет эту таблицу:

| id |
|----|
| 1  |
| 2  |
| 4  |

Если вы хотите получить по одной строке на команду, вам нужно использовать функцию array_agg.

select team, array_agg(id) ids
from (
  select team, id, rank() over (partition by team order by date desc) as row_num
  from table
) t
where row_num = 1
group by team

Этот запрос вернет эту таблицу:

| team |  ids   |
|------|--------|
|  A   | [1, 2] |
|  B   | [4]    |
0 голосов
/ 12 января 2019

Если ваш набор данных большой, рассмотрите аналитическую функцию max в подзапросе:

with cte as (
  select
    id, date, team,
    max (date) over (partition by team) as max_date
  from t
)
select id
from cte
where date = max_date

Условно, max - это O (n), поэтому оно должно быть довольно эффективным. Я не претендую на то, что знаю фактическую реализацию на PostgreSQL, но думаю, что это O (n).

0 голосов
/ 13 января 2019

Еще одна возможность, общая:

select * from t join (select max(date) date,team from t
                        group by team) tt
  using(date,team)
0 голосов
/ 12 января 2019

В этом случае вы можете использовать оконные функции:

select t.*
from (select t.*, rank() over (partition by team order by date desc) as seqnum
      from t
     ) t
where seqnum = 1;

В некоторых базах данных коррелированный подзапрос быстрее с правильными индексами (я не проверял это с Postgres):

select t.*
from t
where t.date = (select max(t2.date) from t t2 where t2.team = t.team);

А если вы хотите, чтобы в каждой команде был только один ряд, то канонический ответ:

select distinct on (t.team) t.*
from t
order by t.team, t.date desc;

Однако в этом случае это не сработает, потому что вам нужны все строки с самой последней даты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...