【问题标题】:Creating customised records in each group of records in table using SQL. Scenario based使用 SQL 在表中的每组记录中创建自定义记录。基于场景
【发布时间】:2020-08-22 09:53:56
【问题描述】:

Tab_X

**Col_1 Col_2   Col_3**
A1      B1      10
A1      B2      7
A2      B1      15
A2      B2      6

输出

**Col_1 Col_2   Col_3** 
A1      B1      10  
A1      B2      7   
**A1        null            3    {10 - 7}**
A2      B1      15  
A2      B2      6   
**A2        Null            9   {15 - 6}**

Col_1 的所有组都应该有一条 col_3 值的新记录,如下所示 = Col_3 {where col_2 = ‘B1’} - SUM(Col_3) {where col_2 ‘B1’}

有人可以建议使用 SQL 来实现这一点吗?

【问题讨论】:

    标签: sql plsql scenarios


    【解决方案1】:
    with Tab_X (Col_1, Col_2, Col_3) as (
        select 'A1', 'B1', 10 from dual union all
        select 'A1', 'B2', 7  from dual union all
        select 'A2', 'B1', 15 from dual union all
        select 'A2', 'B2', 6  from dual
    )
    select *
    from Tab_X
    union all -- UPDATE, thanks @GordonLinoff
    select Col_1
         , null
         , sum(Col_3 * case when Col_2 = 'B1' then 1 else -1 end)
    from Tab_X
    group by Col_1;
    

    评论:

    • 请在您的输入规范中使用 CTE(with 子句)以使回答更方便
    • 请标记数据库供应商的问题。从plsql 标签我猜你有Oracle,不幸的是没有filter (where) 子句,因此sum (case when) 解决方法
    • 也可以使用group by rollup 解决,但我想不出来

    更新:基于group by rollup的解决方案

    with Tab_X (Col_1, Col_2, Col_3) as (
        select 'A1', 'B1', 10 from dual union all
        select 'A1', 'B2', 7  from dual union all
        select 'A2', 'B1', 15 from dual union all
        select 'A2', 'B2', 6  from dual
    )
    select Col_1
         , null
         , case
             when grouping(Col_2) = 1 then sum(Col_3 * case when Col_2 = 'B1' then 1 else -1 end)
             else min(Col_3)
           end as Col_3
    from Tab_X
    group by Col_1, rollup (Col_2)
    

    【讨论】:

    • 我进一步简化了查询重写group by rollup 子句并避免having 子句(覆盖答案,以前的版本历史可用)。
    【解决方案2】:

    我对前一行的 col_3 值使用了“滞后”函数。 并且“Rank”列用于捕获更改 col_1 列(A1 到 A2)。当它更改排名时正在增加。

    with tab_x (col_1, col_2, col_3)
     as (select 'A1', 'B1', 10 from DUAL
         union
         select 'A1', 'B2', 7 from DUAL
         union
         select 'A2', 'B1', 15 from DUAL
         union
         select 'A2', 'B2', 6 from DUAL)  select x.col_1, x.col_2, x.col_3
    from (select col_1,
                 col_2,
                 col_3,
                 null RANK
            from (select col_1,
                         null col_2,
                         LAG (col_3, 1, 0) over (order by col_1) - col_3
                            as col_3,
                         null,
                         RANK ()
                            over (partition by col_1 order by col_1, col_2)
                            RANK
                    from tab_x)
           where RANK = 2
          union all
          select col_1,
                 col_2,
                 col_3,               
                 null RANK
            from tab_x
          order by col_1, col_2) x order by col_1, col_2

    【讨论】:

    • 不鼓励使用纯代码解决方案。添加一些解释可能会有所帮助
    猜你喜欢
    • 2021-12-31
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    相关资源
    最近更新 更多