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

扶醉桌前 提交于 2020-06-29 03:22:32

问题


A bit new to SQL - the db is Snowflake, which I believe is ANSI

Main table shown below. Combinations of same Issue/UPC/Warehouse/Date can be possible, since a new record is added whenever a new issue is reported. Other columns exist, but should not affect this question

The exclude column is what I'm trying to figure out - it should be 'Y' if the desired combination of Issue/UPC/Warehouse and Date is in the Exclusion table, shown below.

The tricky part is the LEVEL column, defining if a UPC/Issue/Warehouse combination must match, or just UPC/Issue, or just UPC. Also, the records in the main table must fall within the Date range to be excluded.

Visually, expected result is this

This solution works for just one level (Issue/UPC/Warehouse), but I can't figure out how to do the other two without overlap and the possibility of excluding records on accident.

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

回答1:


David's answer has covered the right approach to take, using the CASE conditional expression, but ensure that your query also incorporates the level check into each condition explicitly. Here's a verbose example:

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:


I'm not following what your solution is missing, but You can handle multiple different situations/outputs for the column with a case statement. Only the first one that matches will apply so it can prevent overlap.

Something like this:

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
;

You could also use this to invert your logic to specify 'N' situations and default to 'Y' if that makes more sense.




回答3:


If I ignore the level column, then I can just use null to see if there is a match. If that suffices, then:

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

You can use the level column as well (I think the above is clearer). Something like this:

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



回答4:


I agree with what David said, what you need is an update with case statement. Be bit careful with case statement - only the first criteria that is met will be executed. so code for the most common case first, then next most common .. to finally the least common criteria.



来源:https://stackoverflow.com/questions/62442059/sql-set-conditional-value-based-on-varying-criteria-in-another-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!