我有以下表格:
svc_sms:
sms_pk | sms_title
和
svc_sms_msg:
msg_pk | sms_text | msg_status | sms_pk(FK到svc_sms.sms_pk)
我想通过msg_status查询和分组来自const express = require('express');
const app = express();
var blog = require('./routes/blog');
app.use('/blogs', blog);
的所有行,所以我这样做:
svc_sms_msg
现在认为msg.msg_status范围仅在0到4之间,所以我需要得到每个带有sms_status ='x'的sms出现在sms_pk分组中的次数。我需要我的结果是这样的:
SELECT sms.sms_pk, msg.msg_status, COUNT(msg.msg_status) as num
FROM svc_sms_msg as msg
INNER JOIN svc_sms as sms ON sms.sms_pk = msg.sms_pk
GROUP BY sms.sms_pk, msg.msg_status
ORDER BY sms.sms_pk, msg.msg_status
但是当没有'msg_status = x'的行(msg中)时,连接什么也没给我,我需要显示“状态”的大小,即使它们是0的 在我这样做之前:
> sms.sms_pk | msg.msg_status | num
>
> 1 0 1
>
> 1 1 5
>
> 1 2 4
>
> 1 3 20
>
> 1 4 18
>
> 2 0 5
>
> 2 1 0
>
> 2 2 3
>
> 2 3 23
>
> 2 4 0
等等......但事实证明,在我的情况下,它太慢而且不实用。我怎样才能以更有效的方式做到这一点?谢谢
答案 0 :(得分:2)
您可以创建所有状态(0到4)的派生表(下面的All_Status),并将其连接到您的svc_sms,然后将其连接到svc_sms_msg
交叉连接确保每个SVC_SMS都具有所有状态,即使没有消息存在,因此这些记录的计数将为零而不是丢失。通过在sms_pk和" status"上加入svc_sms_msg。我们保留所有交叉连接记录,确保每个状态都分配给每个SMS_PK;因此当msg.msg_status不存在时,计数将为0(为空)
SELECT sms.sms_pk, msg.msg_status, COUNT(msg.msg_status) as num
FROM svc_sms as sms
CROSS JOIN (SELECT unnest(array[0,1,2,3,4]) status) All_Status
LEFT JOIN svc_sms_msg as msg
ON sms.sms_pk = msg.sms_pk
AND All_Status.Status = msg.msg_Status
GROUP BY sms.sms_pk, msg.msg_status
ORDER BY sms.sms_pk, msg.msg_status
仅取决于您是希望为每个状态添加更多列还是为每个状态和sms_pk添加一行。
给定此方法,总行数应等于SMS_Pk的5 *#。
答案 1 :(得分:1)
由于很酷的postgresql功能FILTER
,它可以变得更简单SELECT
msg_pk
,COUNT() FILTER (WHERE msg_status = 0) as cnt_initial
,COUNT() FILTER (WHERE msg_status = 1) as cnt_pending
,COUNT() FILTER (WHERE msg_status = 2) as cnt_sended
FROM svc_sms_msg
GROUP BY sms_pk;
答案 2 :(得分:0)
也许条件聚合可行:
SELECT SUM(CASE WHEN (msg_status = 0) THEN 1 ELSE 0 END) as cnt_initial,
SUM(CASE WHEN (msg_status = 1) THEN 1 ELSE 0 END) as cnt_pending;
SUM(CASE WHEN (msg_status = 2) THEN 1 ELSE 0 END) ) as cnt_sended
FROM svc_sms_msg;
您可以按特定列进行汇总。 。 。所以你可能想要:
SELECT sms_pk, SUM(CASE WHEN (msg_status = 0) THEN 1 ELSE 0 END) as cnt_initial,
SUM(CASE WHEN (msg_status = 1) THEN 1 ELSE 0 END) as cnt_pending;
SUM(CASE WHEN (msg_status = 2) THEN 1 ELSE 0 END) ) as cnt_sended
FROM svc_sms_msg
GROUP BY sms_pk;
我发现在查询中遵循逻辑有点困难,但我认为这就是你要做的事情。
答案 3 :(得分:0)
希望,我理解你的问题。
请查看以下查询。
SELECT sms.sms_pk, msg.msg_status,
COUNT(CASE WHEN msg.msg_status='0' THEN 1 END) as num_0
COUNT(CASE WHEN msg.msg_status='1' THEN 1 END) as num_1
COUNT(CASE WHEN msg.msg_status='2' THEN 1 END) as num_2
COUNT(CASE WHEN msg.msg_status='3' THEN 1 END) as num_3
COUNT(CASE WHEN msg.msg_status='4' THEN 1 END) as num_4
FROM svc_sms as sms
LEFT OUTER JOIN svc_sms_msg as msg ON sms.sms_pk = msg.sms_pk
GROUP BY sms.sms_pk, msg.msg_status
ORDER BY sms.sms_pk, msg.msg_status;