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

问题描述 投票:0回答:4

对SQL有点陌生--数据库是Snowflake,我相信是ANSI标准的

主表如下所示。由于每当报告一个新的问题时,就会增加一条新的记录,因此可以将相同的IssueUPCWarehouseDate组合在一起。其他列存在,但不应该影响这个问题。

enter image description here

我想弄明白的是排除列--如果所需的IssueUPCWarehouse和Date组合在排除表中,它应该是'Y',如下图所示。

enter image description here

棘手的部分是LEVEL列,定义了UPCIssueWarehouse组合是否必须匹配,或者只是UPCIssue,或者只是UPC。另外,主表中的记录必须落在Date范围内才能排除。

从外观上看,预期的结果是这样的

enter image description here

这个方案只对一级(IssueUPCWarehouse)有效,但我想不出如何做另外两级而不重叠,不存在意外排除记录的可能。

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);
sql conditional-statements snowflake-cloud-data-platform ansi
4个回答
1
投票

大卫的回答 已经涵盖了采取的正确方法,用 CASE 条件表达式但要确保你的查询也将级别检查显式地包含在每个条件中。这里有一个啰嗦的例子,我没有听懂你的解决方案,但你可以用case语句处理列的多个不同情况输出。

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
投票

我不明白你的解决方案有什么不足之处 但你可以用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
投票

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

0
投票

我同意David所说的,你需要的是一个带有case语句的更新。要小心使用case语句--只有满足第一个条件的才会被执行。所以先为最常见的情况编码,然后是下一个最常见的...最后是最不常见的条件。

© www.soinside.com 2019 - 2024. All rights reserved.