【问题标题】:How to obtain summary rows where each summary is dependent on another column?如何获取每个摘要都依赖于另一列的摘要行?
【发布时间】:2013-02-27 22:59:57
【问题描述】:

Oracle11g

如何获取每对行满足最小总和的汇总行? 当我指定 where total_lot > N 时,我会排除我想要保留的行。

我想回答这个数据问题:哪些 id 的 KEYS 的总手数大于 6AND 具有 LOCK 的总手数大于 4?

with inventory_items as
(
  select 1 as item_id, 'KEYS' as code, '1020' as sub_code, 4 as lot_size from dual     union all
  select 1 as item_id, 'KEYS' as code, '2210' as sub_code, 4 as lot_size from dual  union all
  select 1 as item_id, 'LOCK' as code, '1610' as sub_code, 3 as lot_size from dual  union all
  select 1 as item_id, 'LOCK' as code, '1031' as sub_code, 2 as lot_size from dual  union all
  select 2 as item_id, 'KEYS' as code, '1020' as sub_code, 2 as lot_size from dual  union all
  select 2 as item_id, 'KEYS' as code, '2210' as sub_code, 1 as lot_size from dual  union all
  select 2 as item_id, 'LOCK' as code, '1610' as sub_code, 1 as lot_size from dual  union all
  select 2 as item_id, 'LOCK' as code, '1031' as sub_code, 3 as lot_size from dual  union all
  select 3 as item_id, 'KEYS' as code, '1031' as sub_code, 8 as lot_size from dual 
  )
  select distinct item_id, code, 
         sum(lot_size) over (partition by item_id, code) as total_lot
  from inventory_items
  order by item_id, code         

期望的结果

  1. ID 有 LOCK 和
  2. ID 有 KEYS 和
  3. KEYS 的 Total_lot 大于 6 并且
  4. LOCK 的 Total_lot 大于 4

输出:

 ITEM_ID   CODE   TOTAL_LOT
 -----     -----  --------
 1         KEYS   8
 1         LOCK   5

【问题讨论】:

    标签: sql oracle11g analytics summary


    【解决方案1】:

    你在寻找这样的东西吗?

    select item_id, code, sum(lot_size)
    from inventory_items ii
    group by item_id, code
    having sum(lot_size) > (case when code = 'KEYS' then 6
                                 when code = 'LOCK' then 4
                            end)
    

    顺便说一句,您的示例代码中的查询是一种非常麻烦的 group by 方式。

    针对您的评论,假设您指的是两者的手数的总和

    select item_id, sum(lot_size)
    from inventory_items ii
    group by item_id
    having sum(case when code = 'KEYS' then lot_size else 0 end) > 6 and
           sum(case when code = 'LOCK' then lot_size else 0 end) > 4
    

    如果您的意思是任何手数都大于一个值,那么在having 子句中使用max() 而不是sum()

    包含代码的最简单方法是将原始数据连接回此代码。这是一种表达方式:

    select *
    from inventory_items ii
    where ii.item_id in (select item_id, sum(lot_size)
                         from inventory_items ii
                          group by item_id
                          having sum(case when code = 'KEYS' then lot_size else 0 end) > 6 and
                                 sum(case when code = 'LOCK' then lot_size else 0 end) > 4
                        )
    

    【讨论】:

    • 戈登,不完全是。我想回答:哪些 id 的 KEYS 的总手数大于 6,而 LOCK 的手数大于 4?您的建议包括 id=3 但我不希望它 b/c 它没有锁。既然你注意到了,我怎样才能在没有 group by 的情况下按 id 获得总和?
    • 戈登,感谢您的回复。第二个查询包含 13 的正确摘要,即锁和密钥的 id=1 之和,但我也想报告代码。当我在 select 和 group by 子句中包含“代码”时,我没有得到预期的结果。不过,你给了我一些想法。
    【解决方案2】:

    这里有一个解决方案。

    说明

    使用 Gordon 的查询选择所有满足数量要求的 item_id。此查询返回 ID=3,因为总 KEYS > 6。

    select item_id, 
           code, 
           sum(lot_size) total_lot
    from inventory_items 
    group by item_id, code
    having sum(lot_size) > (case 
                             when code = 'KEYS' then 6
                             when code = 'LOCK' then 4
                            end)
    

    输出

    ITEM_ID  CODE  TOTAL_LOT
    ------------------------
     1       KEYS  8
     1       LOCK  5
     3       KEYS  8
    

    现在,您需要排除 ID=3,因为您的要求是只包含那些同时具有 KEYS 和 LOCK 的 ID。也就是说,您希望每个 item_id 恰好返回两行。所以取上一个查询,添加一个统计item_id个数的列。

    select item_id,
           code,
           total_lot,
           count(*) over (partition by item_id) as item_count
    from (
    select item_id, 
           code, 
           sum(lot_size) total_lot
    from inventory_items 
    group by item_id, code
    having sum(lot_size) > (case 
                             when code = 'KEYS' then 6
                             when code = 'LOCK' then 4
                            end)
     ) 
    

    输出

    ITEM_ID CODE  TOTAL_LOT ITEM_COUNT
    ------- ---- ---------- ----------
    1       KEYS      8          2
    1       LOCK      5          2
    3       KEYS      8          1
    

    这为您提供了一个用于过滤行数的列,但要使用 你需要再次嵌套。

    select item_id, 
           code,
           total_lot
    from (
     select item_id,
           code,
           total_lot,
           count(*) over (partition by item_id) as item_count
    from (
    select item_id, 
           code, 
           sum(lot_size) total_lot
    from inventory_items 
    group by item_id, code
    having sum(lot_size) > (case 
                             when code = 'KEYS' then 6
                             when code = 'LOCK' then 4
                            end)
     ) 
    ) where item_count=2
    

    输出

     ITEM_ID  CODE  TOTAL_LOT
     ------------------------
     1       KEYS  8
     1       LOCK  5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多