如何使用条件计算 SQL (Oracle) 中的多个列?
Posted
技术标签:
【中文标题】如何使用条件计算 SQL (Oracle) 中的多个列?【英文标题】:How to count multiple columns in SQL (Oracle) with criteria? 【发布时间】:2020-05-27 10:10:01 【问题描述】:我正在开发 SMS-Gateway,它拥有多个不同号码的收费 SMS-服务, 每条发送给客户的短信都有以下 4 种状态(已转发、已送达、已过期、送达失败)
现在我有以下充电系统的 first_table 以及以下详细信息(TABLE-A)
及以下 (TABLE-B) 包含每条已发送 SMS 的状态及其 ID
以下是我预期的最终结果,用于预测每个短信服务的详细信息:
起初我认为这很简单,我只需要使用COUNT(Case when ...)
但就我而言,我有数千个短信号码(服务),所以如果我使用这种方法,它会是这样的:-
COUNT(CASE WHEN a.SMS_SHORT_CODE='1111' AND B.STATUS='forwarded' )
COUNT(CASE WHEN a.SMS_SHORT_CODE='1111' AND B.STATUS='delivered' )
COUNT(CASE WHEN a.SMS_SHORT_CODE='1111' AND B.STATUS='expired' )
COUNT(CASE WHEN a.SMS_SHORT_CODE='1111' AND B.STATUS='delivery failed' )
COUNT(CASE WHEN a.SMS_SHORT_CODE='5000' AND B.STATUS='forwarded' )
COUNT(CASE WHEN a.SMS_SHORT_CODE='5000' AND B.STATUS='delivered' )
COUNT(CASE WHEN a.SMS_SHORT_CODE='5000' AND B.STATUS='expired' )
COUNT(CASE WHEN a.SMS_SHORT_CODE='5000' AND B.STATUS='delivery failed' )
...
...
...
...
...
...
...
当您有许多服务还注意到CASE
只能处理 250 个条件时,上述方法不实用?
那么,使用 SMS-ID 对(表 B)上的(表 A)执行left outer join
并计算每个 SMS 状态并进行如下预测的最佳方法是什么?
【问题讨论】:
【参考方案1】:我建议条件聚合:
select b.SMS_SHORT_CODE,
sum(case when status = 'forwaded' then 1 else 0 end) as count_of_forwaded,
sum(case when status = 'delivered' then 1 else 0 end) as count_of_status,
sum(case when status = 'expired' then 1 else 0 end) as count_of_expired,
sum(case when status = 'delivery failed' then 1 else 0 end) as count_of_delivery_failed
from TABLEB b
group by b.SMS_SHORT_CODE ;
请注意,不需要JOIN
。您要汇总的所有数据都在TABLEB
。
【讨论】:
谢谢,我会尝试,但我需要表 A 的左外连接,因为有些短信是免费的,表 A 只包含收费的短信,这就是我使用连接的原因。 @OsamaAl-Banna。 . .没事儿。您可以使用left join
。但您问的问题不需要它。
我选择这种方法是因为更简单,适用于其他场景,对我来说不太复杂,我想我也需要了解枢轴。【参考方案2】:
请使用以下查询,
select
A.SMS_SHORT_CODE,
case when status = 'forwaded' then count(status ) end as count_of_forwaded,
case when status = 'delivered' then count(status ) end as count_of_status,
case when status = 'expired' then count(status ) end as count_of_expired,
case when status = 'delivery failed' then count(status ) end as count_of_delivery_failed
from TABLEA A
inner join TABLEB B
on (A.SMS_ID = B.SMS_ID)
group by A.SMS_SHORT_CODE, status ;
【讨论】:
【参考方案3】:您可以对那些status
列使用PIVOT
子句(在Oracle 11g 版本中引入):
SELECT sms_short_code,
COUNT_OF_forwarded,
COUNT_OF_delivered,
COUNT_OF_expired,
COUNT_OF_delivery_failed
FROM tableB
PIVOT
(
COUNT(*) FOR status IN ( 'forwarded' AS COUNT_OF_forwarded,
'delivered' AS COUNT_OF_delivered,
'expired' AS COUNT_OF_expired,
'delivery failed' AS COUNT_OF_delivery_failed )
)
例如只用TableB
就够了。
Demo
【讨论】:
感谢 Barbaros Özhan,我会尝试,但我需要与表 A 的表左外连接,因为有些短信是免费的,表 A 只包含收费的短信,这就是我使用连接的原因。 不客气@OsamaAl-Banna,但需要根据需要扩展输出集并通过编辑来详细说明问题。以上是关于如何使用条件计算 SQL (Oracle) 中的多个列?的主要内容,如果未能解决你的问题,请参考以下文章