我有如下表格:
CREATE TABLE public.test_table
(
"ID" serial PRIMARY KEY NOT NULL,
"CID" integer NOT NULL,
"SEG" integer NOT NULL,
"DDN" character varying(3) NOT NULL
)
数据看起来像这样:
ID CID SEG DDN
1 1 1 "711"
2 1 2 "800"
3 1 3 "124"
4 2 1 "711"
5 3 1 "711"
6 3 2 "802"
7 4 1 "799"
8 5 1 "799"
9 5 2 "804"
10 6 1 "799"
我需要按 CID 列对这些数据进行分组,并根据 DDN 列的第一个值获取列计数,但计数必须给我两个不同的信息,无论是否大于 1。
如果不能解释清楚,真的很抱歉。让我告诉你我需要什么..
DDN END TRA
711 1 2
799 2 1
可以看到,DDN:711有1条单次计数记录(ID:4)。这是 END 列。 但是 2 次有多个 SEG 计数(ID:1to3 和 ID:5to6)。这是 TRA 专栏。
我不能确定什么列应该在组子句中!
我的解决方案:
刚刚找到如下解决方案
WITH x AS (
SELECT
(SELECT t1."DDN" FROM public.test_table AS t1
WHERE t1."CID"=t."CID" AND t1."SEG"=1) AS ddn,
COUNT("CID") AS seg_count
FROM public.test_table AS t
GROUP BY "CID"
)
SELECT ddn, COUNT(seg_count) AS "TOTAL",
SUM(CASE WHEN x.seg_count=1 THEN 1 ELSE 0 END) as "END",
SUM(CASE WHEN x.seg_count>1 THEN 1 ELSE 0 END) as "TRA"
FROM x
GROUP BY ddn;
最佳答案
等效的、更快的查询:
SELECT "DDN"
, COUNT(*) AS "TOTAL"
, COUNT(*) FILTER (WHERE seg_count = 1) AS "END"
, COUNT(*) FILTER (WHERE seg_count > 1) AS "TRA"
FROM (
SELECT DISTINCT ON ("CID")
"DDN" -- assuming min "SEG" is always 1
, COUNT(*) OVER (PARTITION BY "CID") AS seg_count
FROM test_table
ORDER BY "CID", "SEG"
) sub
GROUP BY "DDN";
db<> fiddle here
注意事项
CTE 通常较慢,应仅在 Postgres 中需要的地方使用。
这等同于问题中的查询假设每个“CID”的最小“SEG”总是1 - 因为此查询返回具有最小值的行"SEG"而您的查询返回带有 "SEG"= 1
的那个。通常,您会想要“第一”段,而我的查询更可靠地实现了此要求,但这在问题中并不清楚。
COUNT(*)
比 COUNT(column)
稍快,并且不涉及 NULL 值(适用于此处)。相关:
关于 DISTINCT ON
:
聚合 FILTER
语法需要 Postgres 9.4+:
关于sql - 按另一个列值分组和计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52275571/