如何使用条件计算 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) 中的多个列?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 Oracle SQL 中的某些条件将列拆分为 2?

Oracle Apex SQL 中的条件格式(红色文本)

SQL severa 中l数据库如何进行查询

比较两个日期Oracle的多案例

如何使用具有不同 where 条件的多项选择获得结果

保证sqldeveloper运行条件