我有国家名单。每个简短缩写(short)都对应一个国家/地区,但是人们喜欢输入除国家/地区名称之外的其他变量,该国家/地区名称以下面的列表结尾
short nation Students
A A 604
A Austria 6707
A Österreich 3400
AFG Afg 18
AFG Afghanistan 1991
AGL Angola 16
AGN Guinea 2
AL Al 5
AL Albanien 61
ARM Arm 6
ARM Armenien 87
因此,如您所见,计算每个国家的学生总数可以得出2或3个结果。因此很明显,我的问题浮现在脑海中,即是否有可能计算出如下所示的每个短文本分组的总和
short nation Students
A A 604
A Austria 6707
A Österreich 3400
A 10711
AFG Afg 18
AFG Afghanistan 1991
AFG 2009
AGL Angola 16
AGN Guinea 2
AL Al 5
AL Albanien 61
AL 66
ARM Arm 6
ARM Armenien 87
ARM 93
我的代码如下
with natctf as (
SELECT short,
nation,
cast(Studentcount as varchar(6)) as Studentcount
FROM (
SELECT ctf.shorttext as short, ctf.longtext as nation,
count(distinct s.studentid) as Studentcount
from students s
join pupil p on p.id = s.pupilid
join pupilnation pn on pn.pupilid = p.id
join country ctf on ctf.id = pn.coutnryid
Group by ctf.shorttext,ctf.longtext
Order by ctf.shorttext
) t )
SELECT short, initcap(nation), Studentcount
FROM natctf
UNION ALL
SELECT null as short,
cast(count(nation) as varchar(3)) ||' Nations',
cast(SUM(cast(Studentcount as bigint)) as varchar(10)) ||' Students'
FROM natctf
答案 0 :(得分:2)
最好的解决方案是使用分组集,这是一种SQL标准功能,正好适合您的用例:
SELECT ctf.shorttext as short,
ctf.longtext as nation,
count(...)
FROM country AS ctf JOIN ...
GROUP BY GROUPING SETS ((ctf.shorttext, ctf.longtext), (ctf.shorttext))
ORDER BY ctf.shorttext, ctf.longtext
答案 1 :(得分:2)
免责声明:这是PostgreSQL 9.0-9.4版的解决方案。对于 Postgres 9.5 或更高版本,我会使用@LaurenzAlbe的GROUPING SETS
解决方案
WITH count_nations AS ( -- A
SELECT
*,
sum(students) OVER (PARTITION BY short) as total -- B
FROM nations
)
SELECT short, name, students FROM count_nations -- C
UNION -- E
SELECT short, NULL, total FROM count_nations -- D
ORDER BY
short,
name NULLS LAST, -- F
students
A:WITH
子句使查询更具可读性,因为您无需两次编写相同的子查询。
B:窗口函数(https://www.postgresql.org/docs/current/static/tutorial-window.html)SUM
汇总给定帧(此处为short
列)中的所有值。因此,您将获得的国家总数作为单独的列。
子查询的结果:
short name students total
A A 604 10711
A Austria 6707 10711
A Österreich 3400 10711
AFG Afg 18 2009
AFG Afghanistan 1991 2009
AGL Angola 16 16
AGN Guinea 2 2
AL Al 5 66
AL Albanien 61 66
ARM Arm 6 93
ARM Armenien 87 93
C:选择原始列...
D:选择没有名称的新列...
E:UNION
均得到结果。 UNION
使结果与众不同,因此每个国家/地区只获得一行。 (UNION ALL
不会与众不同)
F:对结果进行排序。对于国家行,NULL
值应该是最后一个。
结果:
short name students
A A 604
A Austria 6707
A Österreich 3400
A 10711
AFG Afg 18
AFG Afghanistan 1991
AFG 2009
AGL Angola 16
AGL 16
AGN Guinea 2
AGN 2
AL Al 5
AL Albanien 61
AL 66
ARM Arm 6
ARM Armenien 87
ARM 93
在您的示例中,您仅为具有多行的国家/地区添加额外的行。例如,对于AGN
,您无需添加行。如果您打算这样做,上面的db <> fiddle链接将为您显示解决方案:
WITH
子句UNION
过滤所有国家的row_count > 1
子查询答案 2 :(得分:0)
UNION ALL
一个查询,其中您GROUP BY
的短名和长名以及另一个仅按短名分组的查询。
SELECT x.short,
x.nation,
x.studentcount
FROM (SELECT ctf.shorttext short,
ctf.longtext nation,
count(DISTINCT s.studentid) studentcount
FROM students s
INNER JOIN pupil p
ON p.id = s.pupilid
INNER JOIN pupilnation pn
ON pn.pupilid = p.id
INNER JOIN country ctf
ON ctf.id = pn.coutnryid
GROUP BY ctf.shorttext,
ctf.longtext
UNION ALL
SELECT ctf.shorttext short,
NULL nation,
count(DISTINCT s.studentid) studentcount
FROM students s
INNER JOIN pupil p
ON p.id = s.pupilid
INNER JOIN pupilnation pn
ON pn.pupilid = p.id
INNER JOIN country ctf
ON ctf.id = pn.coutnryid
GROUP BY ctf.shorttext) x
ORDER BY x.short,
x.nation NULLS LAST;
请注意,按短名称分组的查询的计数不得为计数的总和,其他查询将返回。那是因为数量不同。如果对于一个学生来说,有多个不同的长名和一个短名,则它们会被计入长名的每个组中,但在短名组中只会被计数一次。