代码之家  ›  专栏  ›  技术社区  ›  not_ur_avg_cookie

具有多个方案的嵌套case语句

  •  0
  • not_ur_avg_cookie  · 技术社区  · 5 年前

    我有一张桌子,有两个不同的项目(a&B)。b项基本上是重复的,必须删除或重新分配给A。我正在尝试实现一个输出字符串,它告诉我该做什么。规则如下:

    第二,如果有两个项目,显然必须重新分配或删除。如果项目B的日期与项目A的日期匹配,则可以将其删除。如果项目B的日期与项目A的任何日期不匹配,则必须重新分配。

    下面是一些示例数据,在这些数据中,我试图找出case表达式逻辑:

    declare @table table (
    item varchar(1),
    date date )
    
    insert into @table values ('a' , '2019-01-01')
    insert into @table values ('a' , '2019-01-02')
    insert into @table values ('a' , '2019-01-03')
    insert into @table values ('a' , '2019-01-04')
    insert into @table values ('a' , '2019-01-05')
    insert into @table values ('a' , '2019-01-06')
    insert into @table values ('a' , '2019-01-07')
    insert into @table values ('a' , '2019-01-08')
    insert into @table values ('a' , '2019-01-09')
    insert into @table values ('a' , '2019-01-11')
    insert into @table values ('b' , '2019-01-10')
    

    起初,我尝试了这些case语句,但它们给了我错误的输出,例如所附的示例:

     select case when (select count(distinct item) from @table where item in ('a','b'))  <= 1 
        then case when (select distinct item from @table where item in ('a','b')) = 'a' then 'no action needed!' 
             else 'reassign to A' end
    else 'delete B' end result
    

    这是我第二次尝试使用case表达式,但现在失败了,我需要一条建议来让它起作用:

            select case when (select count(distinct item) from @table where item in ('a','b'))  > 1 
                    then case when (select count(*) from @table a join @table b on a.date = b.date 
                            where a.item in ('b') and  b.item in ('a')) <> (select count(*) from @table where item in ('b'))
                            then 'check what overlaps and whats not' 
                            else 'delete all rows from A' end  end
        case when  (select count(distinct item) from @table where item in ('a','b'))  =< 1 
                    then case when (select distinct item from @table where item in ('a','b')) <> (select 'a') then  'reassign to A'
             else 'no action needed!'  end
    

    0 回复  |  直到 5 年前
        1
  •  1
  •   pwilcox    5 年前

    我认为你的样本数据不足以涵盖你的所有情况。以下是我的建议:

    declare @table table (item varchar(1), date date )
    
    insert @table values 
        ('a', '2019-01-01'), -- unique and in 'a'
        ('b', '2019-01-02'), -- unique and in 'b' 
        ('a' , '2019-01-03'), -- once in 'a' and once in 'b'
        ('b' , '2019-01-03'); -- once in 'a' and once in 'b'
    

    请注意,如果“a”中有两个相同的日期,或者“b”中有两个相同的日期,则不会提及会发生什么情况。所以我假设这是不可能的,通过你的接口或数据输入过程。

    您可以从使用窗口函数中获益。它们给出了由某些列分组划分的行值的出现次数。在您的例子中,您希望获得日期出现的计数,而不管它是“a”项还是“b”项。然后根据这些分区的计数,编写这些case语句就容易了一点。

    注意下面发生的事情:

    select      *,
    
                action = 
                    case 
                    when item = 'a' then 'No Action Needed'
                    when n = 1 then 'Reassign to A'
                    else 'Delete'
                    end
    
    from        (
                    select  *,
    
                            -- times row value for 'date' occurs in parent dataset
                            n = count(*) over (partition by date)
    
                    from    @table
                ) counted;
    

    enter image description here

    当然,你也可以让这个过程自动化。假设您将上面查询的结果放入名为#analysis的临时表中。您可以在merge语句中使用它:

    merge @table t
    using #analysis a
        on t.date = a.date
        and t.item = a.item
    
    when matched and action = 'Reassign to A' then 
        update set item = 'a'
    
    when matched and action = 'Delete' then
        delete;
    

    现在如果你 select * from @table 你会发现这是为你做的:

    enter image description here