ORACLE上的Tricky GROUP BY问题

Aja*_*tis 6 sql oracle

我目前正面临一个我的Oracle知识无法解决的问题,我绝对不是数据库专家,这就是为什么我问你是否有任何想法如何解决我的SQL查询问题.

这是我的问题,我有两个表,让我们称它们为DEVICE_TABLE和COUNT_TABLE

COUNT_TABLE看起来像:

    DEVICE (Int) PK         |       QUANTITY (Int)
- - - - - - - - - - - - - - - - - - - - - - - - - - -
        1001                |              4
- - - - - - - - - - - - - - - - - - - - - - - - - - -
        1002                |             20
- - - - - - - - - - - - - - - - - - - - - - - - - - - 
        1003                |              1
…

DEVICE_TABLE看起来像:

     ID (Int) PK            |      WiFi (String)            |     Email (String)          |   Bluetooth(String)           |   …
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        1001                |             Yes               |               No            |                 No            |   …
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        1002                |             Yes               |               Yes           |                 No            |   …
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        1003                |             Unknown           |               Unknown       |                 Yes           |   …
…

限制是:

DEVICE_TABLE.ID = COUNT_TABLE.DEVICE

WiFi,电子邮件,蓝牙...是只能是"是","否"或"未知"的字符串

最后,我的SQL请求结果是预期的(基于我的例子):

         Feature        |            Yes           |              No            |            Unknown          
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
        WiFi            |             24           |                 0          |                 1                  
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
       Email            |             20           |                 4          |                 1                  
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    Bluetooth           |              1           |                24          |                 0                   
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
…

简而言之,此请求的目的是将与特定功能兼容的所有设备数量相加.

如果您对如何实现这一点有任何线索,请提前感谢您!(也许这是不可能的......)

Ren*_*ger 3

在Oracle 11中,您可以将pivot子句与子句一起使用unpivot

with 
count_table as (
     select 1001 device_id,  4 quantity from dual union all
     select 1002 device_id, 20 quantity from dual union all
     select 1003 device_id,  1 quantity from dual 
),
device_table as (
     select 1001 id, 'Yes'     wifi, 'No'       email, 'No'  bluetooth from dual union all
     select 1002 id, 'Yes'     wifi, 'Yes'      email, 'No'  bluetooth from dual union all
     select 1003 id, 'Unknown' wifi, 'Unknown'  email, 'Yes' bluetooth from dual 
)
----------------------------------------
select * from (
      select
        feature,
        yes_no_unknown,
        sum(quantity)  quantity
      from 
         count_table  c join 
         device_table d on c.device_id = d.id
      unpivot  ( yes_no_unknown
                 for feature in (wifi, email, bluetooth)
      ) 
      group by 
      feature,
      yes_no_unknown
)  
pivot ( sum (quantity)
        for yes_no_unknown in ('Yes' as yes, 'No' as no, 'Unknown' as unknown)
)
;
Run Code Online (Sandbox Code Playgroud)

或者,您可能希望将两个现有表连接到包含三个所需行的值的第三个表。它可能也更容易阅读:

with 
count_table as (
     select 1001 device_id,  4 quantity from dual union all
     select 1002 device_id, 20 quantity from dual union all
     select 1003 device_id,  1 quantity from dual 
),
device_table as (
     select 1001 id, 'Yes'     wifi, 'No'       email, 'No'  bluetooth from dual union all
     select 1002 id, 'Yes'     wifi, 'Yes'      email, 'No'  bluetooth from dual union all
     select 1003 id, 'Unknown' wifi, 'Unknown'  email, 'Yes' bluetooth from dual 
)
----------------------------------------
select
   f.txt,
   sum(case when ( f.txt = 'wifi'      and d.wifi      = 'Yes' ) or
                 ( f.txt = 'email'     and d.email     = 'Yes' ) or
                 ( f.txt = 'bluetooth' and d.bluetooth = 'Yes' ) 
            then   c.quantity
            else   0 end
      ) yes,
   sum(case when ( f.txt = 'wifi'      and d.wifi      = 'No' ) or
                 ( f.txt = 'email'     and d.email     = 'No' ) or
                 ( f.txt = 'bluetooth' and d.bluetooth = 'No' ) 
            then   c.quantity
            else   0 end
      ) no,
   sum(case when ( f.txt = 'wifi'      and d.wifi      = 'Unknown' ) or
                 ( f.txt = 'email'     and d.email     = 'Unknown' ) or
                 ( f.txt = 'bluetooth' and d.bluetooth = 'Unknown' ) 
            then   c.quantity
            else   0 end
      ) unknown
from 
   count_table  c                                   join 
   device_table d on c.device_id = d.id     cross   join
   (
        select 'wifi'      txt from dual union all
        select 'email'     txt from dual union all
        select 'bluetooth' txt from dual
   ) f
group by 
    f.txt;
Run Code Online (Sandbox Code Playgroud)