获取DISTINCT ON中重复行的计数

时间:2018-06-26 09:02:58

标签: sql postgresql

在使用SELECT的任何DISTINCT ON查询中,如何才能另外获得结果集中每一行的重复次数?

例如,

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

这只会返回每个建筑物的第一个结果。我想添加另一列,所以结果看起来像这样:

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

“存储空间”中的人数超过鲍勃的人数。我正在使用Postgres 10。

3 个答案:

答案 0 :(得分:5)

您可以使用窗口功能:

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;

答案 1 :(得分:1)

您可以简单地使用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)

答案 2 :(得分:-1)

使用窗口功能吗?

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
);