我有一张如下表:
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:1到3和ID:5到6)。这是TRA专栏。
我不能确定group子句中应该有哪个列!
刚刚找到了如下的解决方案
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 <>小提琴here
笔记:
"SEG" = 1
的行。通常情况下,您会希望“第一个”段和我的查询更可靠地实现此要求,但问题并不清楚。COUNT(*)
比COUNT(column)
稍微快一点,而且不涉及NULL值(适用于此处)。有关:
PostgreSQL: running count of rows for a query 'by minute'DISTINCT ON
:
Select first row in each GROUP BY group?FILTER
语法需要Postgres 9.4+:
SQL count if columns这是我提出的解决方案,我猜这个查询可以简化。
CREATE TABLE test_table
(
ID serial PRIMARY KEY NOT NULL,
CID integer NOT NULL,
SEG integer NOT NULL,
DDN character varying(3) NOT NULL
);
insert into test_table(CID,SEG,DDN)
values
( 1, 1, '711'),
( 1, 2, '800'),
( 1, 3, '124'),
( 2, 1, '711'),
( 3, 1, '711'),
( 3, 2, '802'),
( 4, 1, '799'),
( 5, 1, '799'),
( 5, 2, '804'),
( 6, 1, '799');
with summary as (with ddn_t as (select cid,ddn,row_number() OVER( PARTITION BY cid)from test_table)
select a.cid,count(distinct a.ddn),b.ddn
from ddn_t a
join ddn_t b on b.cid=a.cid and b.row_number=1
group by a.cid, b.ddn)
select ddn,
sum (case when count >1 then 1 else 0 end) as TRA,
sum (case when count = 1 then 1 else 0 end) as END
from summary
group by ddn;