SQL:根据另一个表中的不同条件设置条件值

时间:2020-06-18 03:49:23

标签: sql conditional-statements snowflake-cloud-data-platform ansi

SQL有点新-数据库是Snowflake,我相信它是ANSI

主表如下所示。相同发行/ UPC /仓库/日期的组合是可能的,因为每当报告新发行时都会添加新记录。存在其他列,但不应影响此问题

enter image description here

排除栏是我要弄清楚的-如果“排除”表中的Issue / UPC / Warehouse和Date所需的组合位于“ Y”,如下所示。

enter image description here

棘手的部分是LEVEL列,用于定义UPC /问题/仓库组合是否必须匹配,还是仅UPC /问题,还是UPC。另外,主表中的记录必须在“日期”范围内才能排除。

视觉上,预期的结果是这个

enter image description here

此解决方案仅适用于一个级别(问题/ UPC /仓库),但我无法弄清楚如何在不重叠的情况下执行另外两个级别,并且无法排除意外记录。

update t
set exclude = 'Y'
where exists (select 1
              from exclusions e
              where e.issue_code = t.issue_code and
              e.upc = t.upc and
              e.warehouse = t.warehouse and
              t.date between e.date_from and e.date_to);

4 个答案:

答案 0 :(得分:2)

我没有关注您缺少的解决方案,但是您可以使用case语句处理该列的多种不同情况/输出。只有匹配的第一个匹配项才适用,这样可以防止重叠。

类似这样的东西:

update t
set exclude = CASE
    WHEN EXISTS 
        (select 1
         from exclusions e
         where e.issue_code = t.issue_code and
             e.upc = t.upc and
             e.warehouse = t.warehouse and
             t.date between e.date_from and e.date_to
        ) THEN 'Y'
    WHEN --Other situation where it meets your criteria
        THEN 'Y'
    ELSE 'N'
END
;

您还可以使用它来反转逻辑以指定“ N”个情况,如果更有意义,则默认为“ Y”。

答案 1 :(得分:2)

David's answer已涵盖使用CASE conditional expression的正确方法,但请确保您的查询还将级别检查显式纳入每个条件。这是一个详细的示例:

update t
set exclude = case
    when exists(
        select 1
        from exclusions e
        where 
                e.warehouse = t.warehouse
            and e.upc = t.upc
            and e.issue_code = t.issue_code
            and t.date between e.date_from and e.date_to
            and e.level = 'UPC/ISSUE/WAREHOUSE'
    ) then 'Y'
    when exists(
        select 1
        from exclusions e
        where 
                e.issue_code = t.issue_code
            and e.upc = t.upc
            and t.date between e.date_from and e.date_to
            and e.level = 'UPC/ISSUE'
    ) then 'Y'
    when exists(
        select 1
        from exclusions e
        where 
                e.upc = t.upc
            and t.date between e.date_from and e.date_to
            and e.level = 'UPC'
    ) then 'Y'
    else ''
end;

答案 2 :(得分:1)

如果我忽略level列,那么我可以使用null来查看是否存在匹配项。如果足够,那么:

update t
    set exclude = 'Y'
    where exists (select 1
                  from exclusions e
                  where (e.issue_code = t.issue_code or e.issue_code is null) and
                        (e.upc = t.upc or e.upc is null) and
                        (e.warehouse = t.warehouse or e.warehouse is null) and
                        t.date between e.date_from and e.date_to
                 );

也可以使用level列(我认为以上更清楚)。像这样:

update t
    set exclude = 'Y'
    where exists (select 1
                  from exclusions e
                  where (e.issue_code = t.issue_code or e.level not like '%ISSUE%') and
                        (e.upc = t.upc or e.level not like '%UPC%') and
                        (e.warehouse = t.warehouse or e.level like '%WAREHOUSE%') and
                        t.date between e.date_from and e.date_to
                 );

答案 3 :(得分:0)

我同意戴维所说的,您需要的是对案例陈述的更新。 请谨慎对待case语句-仅执行符合条件的第一个条件。 因此,首先针对最常见的情况编写代码,然后针对最不常见的条件编写下一个最常见的代码。