PostgreSQL使用COUNT形成统计结果

时间:2014-04-21 20:58:17

标签: sql postgresql

我有几张桌子组成了现场/工作室音乐的媒体目录,其中每个媒体项目都有零个显示日期,CD和与之相关的乙烯基。我现在的查询提取的统计信息会导致所有可用媒体项的表格数据集。我现在无法扩展查询以在每个关联的表中包含更精细的统计信息。

架构:

media(id , title)

cd(media_fk, type)

vinyl(media_fk)

gig(id, date)

media_gigs(gig_fk, media_fk)

我到目前为止的查询:

SELECT m.id, m.title, COUNT(DISTINCT c.id) as cds, COUNT(DISTINCT v.id) as vinyl, gig.id as gid, gig.date as gdate FROM media m LEFT JOIN cd c on m.id = c.media LEFT JOIN vinyl v on m.id = v.media LEFT JOIN media_gigs g on m.id = g.media LEFT JOIN gig gig on g.gig = gig.id GROUP BY m.id, gig.id;

产生:

id |  title  | cds | vinyl |           gid            |   gdate    
---+---------+-----+-------+--------------------------+------------
 1 | title 1 |   5 |     1 | may-11-1989-kawasaki     | 1989-05-11
 1 | title 1 |   5 |     1 | may-13-1989-tokyo        | 1989-05-13
 2 | title 2 |   6 |     0 | apr-29-1998-nagoya       | 1998-04-29
 2 | title 2 |   6 |     0 | may-6-1998-tokyo         | 1998-05-06
 2 | title 2 |   6 |     0 | may-7-1998-tokyo         | 1998-05-07
 3 | title 3 |   6 |     2 | dec-1-1986-new-york-city | 1986-12-01
 3 | title 3 |   6 |     2 | dec-5-1986-quebec-city   | 1986-12-05
 3 | title 3 |   6 |     2 | nov-19-1986-tokyo        | 1986-11-19
 3 | title 3 |   6 |     2 | nov-20-1986-tokyo        | 1986-11-20

cd.type[silver,cdr,pro-cdr]的枚举类型,我想要添加到结果中。因此,最终目标是增加3个附加列,这些列是与每个媒体项相关联的cd类型的计数。我没有使用COUNT找到正确的语法,或者根据其类型聚合cd,因此正在寻找正确方向的推送。我对SQL很新,所以到目前为止我可能有点天真。

使用PG 9.3。

2 个答案:

答案 0 :(得分:2)

您可以使用CASE函数确定cd类型并根据结果执行SUM,如下所示:

SELECT 
m.id, 
m.title, 
COUNT(DISTINCT c.id) as cds, 
COUNT(DISTINCT v.id) as vinyl, 
gig.id as gid, gig.date as gdate,
SUM(case cd.type
           when 'silver' then 1
           else 0
           end) silver,
SUM(case cd.type
           when 'cdr' then 1
           else 0
           end) cdr,
SUM(case cd.type
           when 'pro-cdr' then 1
           else 0
           end) pro_cdr
FROM media m
LEFT JOIN cd c on m.id = c.media
LEFT JOIN vinyl v on m.id = v.media 
LEFT JOIN media_gigs g on m.id = g.media 
LEFT JOIN gig gig on g.gig = gig.id
GROUP BY m.id, gig.id;

<强>参考

  1. Conditional Expressions on PostgreSQL 9.3 Manual
  2. Enumerated Types on PostgreSQL 9.3 Manual

答案 1 :(得分:0)

正如其他海报所提到的,您可以在c.type列上使用SUM(CASE WHEN <cond1> THEN 1 ELSE 0)构造执行此操作。

我想提及您的SQL还有其他一些问题:

错误使用LEFT JOIN

您可以将值分组为NULL:gig.id.这可能是因为LEFT JOIN的使用不正确。如果要在结果集中保留连接表中没有匹配项的行,则仅使用左连接。

所以在CD表上左连接是正确的,因为你也希望能够显示有0个CD。在media_gigs和gigs表上你可能想要一个INNER JOIN,因为总是必须匹配。

编辑:我错误地认为这是不正确的。我从样本数据中假设您不想显示没有演出的媒体。

非分组,非汇总列

在查询中,选择未分组的列,这些列不是聚合函数(如SUM,COUNT)。虽然一些Db方言可能接受这一点,但这是不好的做法。例如,请执行以下查询:

SELECT x, y, SUM(z) FROM t
GROUP BY x;

如果y在功能上不依赖于x,也就是说,如果x的一个值可以有不同的y值,则不清楚应该显示这些值中的哪一个。因此,您应该像这样写:

SELECT x, y, SUM(z) FROM t
GROUP BY x, y;