SELECT 字段上的 DISTINCT 或 GROUP BY
SELECT DISTINCT or GROUP BY on field
我的数据库中有一个 table 记录员工全天的每个电话。
每条记录都是支线打来的电话
如果一个分行每天拨打 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: 对不起,英语不好,我的不好。
可能的解决方案:
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;
Select 同一日期没有其他行更早的一行:
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。
使用 ::date
的转换暗示您正在使用 Postgres。在这种情况下,通过使用 distinct on()
运算符可以很容易地获得“ 每个支线当天的第一个呼叫 ”:
SELECT DISTINCT ON (branch) branch, date
FROM table
WHERE date::date = '2015-12-03'::date
ORDER BY branch, date;
另一种解决此类查询的可能性是使用 window 函数:
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 转换)
我的数据库中有一个 table 记录员工全天的每个电话。
每条记录都是支线打来的电话
如果一个分行每天拨打 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: 对不起,英语不好,我的不好。
可能的解决方案:
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;
Select 同一日期没有其他行更早的一行:
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。
使用 ::date
的转换暗示您正在使用 Postgres。在这种情况下,通过使用 distinct on()
运算符可以很容易地获得“ 每个支线当天的第一个呼叫 ”:
SELECT DISTINCT ON (branch) branch, date
FROM table
WHERE date::date = '2015-12-03'::date
ORDER BY branch, date;
另一种解决此类查询的可能性是使用 window 函数:
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 转换)