选择字段上的DISTINCT或GROUP BY

时间:2015-12-03 13:59:18

标签: sql postgresql group-by distinct greatest-n-per-group

我的数据库上有一张表,记录了员工全天的每次通话。

每条记录都是分支线的调用。

如果一个分支机构每天拨打50个电话,我们将在DB上有50条记录:

branch |            date            
-------+----------------------------
 72489 | 2015-12-03 08:03:58
 34002 | 2015-12-03 08:03:59
 78700 | 2015-12-03 08:05:37
 78700 | 2015-12-03 08:05:53
 78700 | 2015-12-03 08:05:57
 78700 | 2015-12-03 08:06:24

我想做的是接听每个支线的第一天电话。

我尝试使用DISTINCT:

SELECT DISTINCT branch, date FROM table WHERE date::date='2015-12-03'::date;

据说DISTINCT会避免在分支上重复,但结果是:

branch |            date           
-------+----------------------------
 34002 | 2015-12-03 07:58:24
 34002 | 2015-12-03 08:00:40
 59754 | 2015-12-03 08:01:31
 34002 | 2015-12-03 08:01:56
 59754 | 2015-12-03 08:02:09
 57764 | 2015-12-03 08:02:17
 59754 | 2015-12-03 08:02:28

我在那里有一些重复。

我喜欢的结果是:

branch |            date            
-------+----------------------------
 34002 | 2015-12-03 07:58:24
 59754 | 2015-12-03 08:01:31
 59754 | 2015-12-03 08:02:09

我尝试使用GROUP BY:

SELECT branch, date FROM table WHERE date::date='2015-12-03'::date GROUP BY branch;

但是得到这个错误:

错误:列“table.date”必须出现在GROUP BY子句中或用于聚合函数。

有人可以帮我吗?

PS:对不起英文,我的不好。

3 个答案:

答案 0 :(得分:1)

使用::date进行演员表示您正在使用Postgres。在这种情况下,使用distinct on()运算符来获取“每个分支行的第一天调用”非常简单:

SELECT DISTINCT ON (branch) branch, date 
FROM table 
WHERE date::date = '2015-12-03'::date
ORDER BY branch, date;

解决此类查询的另一种可能性是使用窗口函数:

select branch, date
from (
   select branch, date,  
          row_number() over (partition by branch order by date) as rn
   where cast(date as date) = date '2015-12-03'
) t
where rn = 1
order by branch;

distinct on ()解决方案是Postgres特有的,第二个解决方案是ANSI SQL(使用ANSI日期文字和ANSI转换)

答案 1 :(得分:0)

可能的解决方案:

SELECT 
    branch, 
    (   
        select 
            date 
        from 
            table tb 
        where 
            tb.branch = table.branch
    ) as date 
FROM 
    table 
GROUP BY
    branch
WHERE 
    date::date='2015-12-03'::date;

答案 2 :(得分:0)

只要同一日期的其他行不在之前,就选择一行:

SELECT branch, date
FROM table t1
WHERE not exists (select 1 from table t2
                  where cast(t1.date as date) = cast(t2.date as date)
                    and t2.date < t1.date)

ANSI SQL兼容。