我们如何向结果集中添加一列以显示 PostgreSQL 中的计数?

How do we add a column to resultset to show count in PostgreSQL?

我运行在 PostgreSQL DB 上进行以下查询,以获取每个通道在不同日期的状态。

SELECT ch.name,
   date(msg.date_created),
   msg.status
FROM message msg,
 channel ch
WHERE msg.status !='TRANSFORMED'
AND msg.channel_id = ch.id
AND msg.date_created BETWEEN to_date('2015-01-10', 'YYYY-MM-DD') AND to_date('2015-01-11', 'YYYY-MM-DD');

它以下列格式获取数据:

Channel_Name,Date,Status
CHANNEL_01,1/10/2015,SENT
CHANNEL_04,1/10/2015,QUEUED
CHANNEL_02,1/10/2015,QUEUED
CHANNEL_02,1/10/2015,FILTERED
CHANNEL_03,1/10/2015,QUEUED
CHANNEL_02,1/10/2015,SENT
CHANNEL_01,1/10/2015,SENT
CHANNEL_03,1/10/2015,ERROR
CHANNEL_01,1/10/2015,SENT
CHANNEL_03,1/10/2015,SENT
CHANNEL_03,1/10/2015,ERROR
CHANNEL_04,1/10/2015,SENT
CHANNEL_03,1/10/2015,SENT
CHANNEL_03,1/10/2015,FILTERED
CHANNEL_04,1/10/2015,ERROR
CHANNEL_03,1/10/2015,SENT
CHANNEL_03,1/10/2015,ERROR
CHANNEL_03,1/10/2015,SENT
CHANNEL_03,1/10/2015,FILTERED
CHANNEL_03,1/10/2015,QUEUED
CHANNEL_04,1/10/2015,FILTERED

但我想计算消息的状态并显示在按名称和日期分组的列中。我应该如何用 "group by" 重写查询以达到如下预期结果?

Channel_Name,Date,SENT,QUEUED,ERROR,FILTERED
CHANNEL_01,1/10/2015,3,0,0,0
CHANNEL_02,1/10/2015,1,0,0,1
CHANNEL_02,1/11/2015,0,1,0,0
CHANNEL_03,1/10/2015,3,2,1,2
CHANNEL_03,1/11/2015,1,0,2,0
CHANNEL_04,1/10/2015,1,1,1,1

作为中间步骤,您可以 GROUP BY ch.name, date(msg.date_created), msg.status 并计算每个频道名称和日期的每个状态的消息数,如下所示:

SELECT ch.name,
   date(msg.date_created),
   msg.status,
   COUNT(*)
FROM message msg,
 channel ch
WHERE msg.status !='TRANSFORMED'
AND msg.channel_id = ch.id
AND msg.date_created BETWEEN to_date('2015-01-10', 'YYYY-MM-DD') AND to_date('2015-01-11', 'YYYY-MM-DD')
GROUP BY ch.name, date(msg.date_created), msg.status;

这应该为您提供以下形式的输出:

CHANNEL_01,1/10/2015,SENT,3
CHANNEL_02,1/10/2015,QUEUED,1
CHANNEL_02,1/11/2015,ERROR,1

这离最终想要的结果只有几步之遥。

您可以使用 SUM(CASE),为每个状态值重复此构造:

SELECT ch.name,
   date(msg.date_created),
   SUM(CASE WHEN msg.status = 'SENT' THEN 1 ELSE 0 END) as SENT,
   ... -- same for other statuses
FROM message msg,
 channel ch
WHERE msg.status !='TRANSFORMED'
AND msg.channel_id = ch.id
AND msg.date_created BETWEEN to_date('2015-01-10', 'YYYY-MM-DD') AND to_date('2015-01-11', 'YYYY-MM-DD')
GROUP BY ch.name, date(msg.date_created);