Получить количество повторяющихся строк в DISTINCT ON - PullRequest
0 голосов
/ 26 июня 2018

В любом запросе SELECT, где используется DISTINCT ON, как дополнительно получить количество дубликатов для каждой строки в наборе результатов?

Взять, к примеру,

SELECT
  DISTINCT ON (building)
  building,
  name
FROM ...
WHERE ...

Это вернет только первый результат для каждого здания. Я хочу добавить еще один столбец, чтобы результаты выглядели так:

name | building | excluded
Fred | Office   | 0
Bob  | Storage  | 3

когда в хранилище больше людей, чем Боба. Я использую Postgres 10.

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Использовать оконные функции?

select
first_value(name) over (partition by building order by /* your order */) first_name
first_value(building) over (partition by building order by  /* your order */) building,
count(*) over (partition by building order by /* your order */) - 1 as excluded
from (
    select name, building
    from my_source_table
);
0 голосов
/ 26 июня 2018

Вы можете просто использовать group by вместо distinct on (чтобы избежать оконных функций):

with data (name, building) as (
  values 
    ('Bob', 'Storage'),
    ('Bob', 'Storage'),
    ('Bob', 'Storage'),
    ('Bob', 'Storage'),
    ('Fred', 'Office'),
    ('Tim', 'Home'),
    ('Tim', 'Home')
)   
select min(name), building, count(*)- 1 as excluded
from data
group by building
order by building;

 min  | building | excluded 
------+----------+----------
 Tim  | Home     |        1
 Fred | Office   |        0
 Bob  | Storage  |        3
(3 rows)
0 голосов
/ 26 июня 2018

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

with data (name, building) as (
  values 
    ('Bob', 'Storage'),
    ('Bob', 'Storage'),
    ('Bob', 'Storage'),
    ('Bob', 'Storage'),
    ('Fred', 'Office'),
    ('Tim', 'Home'),
    ('Tim', 'Home')
)
select distinct on (building) *, 
       count(*) over (partition by building) - 1 as excluded
from data
order by building;

возвращается:

name | building | excluded
-----+----------+---------
Tim  | Home     |        1
Fred | Office   |        0
Bob  | Storage  |        3

Это работает, потому что оконная функция оценивается до distinct on ()

Однако это означает, что нужно выполнять какую-то работу дважды. Я думаю, что было бы быстрее повторно использовать раздел «работа», чтобы также отфильтровать дубликаты:

with ranked as (
  select *, 
         count(*) over w - 1 as excluded, 
         row_number() over w as rn
  from your_table
  window w as (partition by building)
) 
select *
from ranked
where rn = 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...