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

SQL: Set conditional value based on varying criteria in another table

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

主要 table 如下所示。相同 Issue/UPC/Warehouse/Date 的组合是可能的,因为每当报告新问题时都会添加新记录。其他列存在,但应该不会影响这个问题

排除列是我想要弄清楚的 - 如果 Issue/UPC/Warehouse 和日期的所需组合在排除 table 中,它应该是 'Y',如下所示.

棘手的部分是 LEVEL 列,定义 UPC/Issue/Warehouse 组合是否必须匹配,或者只是 UPC/Issue,或者只是 UPC。此外,主要 table 中的记录必须在要排除的日期范围内。

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

此解决方案仅适用于一个级别 (Issue/UPC/Warehouse),但我不知道如何在不重叠的情况下执行其他两个级别以及排除意外记录的可能性。

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);

我没有遵循您的解决方案所缺少的内容,但您可以使用 case 语句为列处理多个不同的 situations/outputs。只有第一个匹配的才会应用,这样可以防止重叠。

像这样:

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' 如果这样更有意义。

我同意 David 所说的,您需要的是带有 case 语句的更新。 小心处理 case 语句——只有满足的第一个条件才会被执行。 所以首先为最常见的情况编写代码,然后是最常见的......最后是最不常见的标准。

has covered the right approach to take, using the 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;

如果我忽略 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
                 );