SQL - 使用窗口和 case 语句展平表

标签 sql sql-server case windowing

第一次提问者 -- 我在 SqlServer 2012 中结合案例逻辑和窗口时遇到一些问题。我需要展平如下所示的数据结构,因此之后我将针对这些结果运行 MAX 语句。我使用 case/when 逻辑为每个 xID 指定一个“所有者”。我的挑战是我一直得到错误的结果,而且我无法确定我做错了什么。

这是 case/when 逻辑和表结构。对于“Owner”列,我需要评估三个条件,并尝试使用 FIRST_VALUE() 来选择 case 语句的输出。 case 语句中的逻辑工作正常,但是当我尝试使用窗口函数将值应用于每个 xID 时,它返回错误的值。

FIRST_VALUE(case
when [partnerType] = 'Giver' and [partnerAgree] = 'True' then [partnerGroup]
when [partnerType] = 'Impacted' and [partnerAgree] = 'True' then [partnerGroup]
when [Stakeholder No#] = 1 and [partnerAgree] <> 'True' then [partnerGroup]
else Null end) over (partition by [xID] order by [yID])
as 'Owner'

Desired Results --------------------------

|xID|yID| Owner     |partnerType| partnergrp|partnerAgree
|100|  1| grp_Banana|Taker      |grp_Apple  |TRUE
|100|  2| grp_Banana|Giver      |grp_Banana |TRUE
|100|  3| grp_Banana|Taker      |grp_Banana |FALSE
|101|  1| grp_Carrot|Taker      |grp_Carrot |TRUE
|101|  2| grp_Carrot|Giver      |grp_Danish |FALSE
|101|  3| grp_Carrot|Taker      |grp_Banana |TRUE
|101|  4| grp_Carrot|Taker      |grp_Danish |FALSE

Results I'm getting --------------------------

|xID|yID| Owner     |partnerType| partnergrp|partnerAgree
|100|  1| grp_Apple |Taker      |grp_Apple  |TRUE
|100|  2| grp_Apple |Giver      |grp_Banana |TRUE
|100|  3| grp_Apple |Taker      |grp_Banana |FALSE
|101|  1| grp_Carrot|Taker      |grp_Carrot |TRUE
|101|  2| grp_Carrot|Giver      |grp_Danish |FALSE
|101|  3| grp_Carrot|Taker      |grp_Banana |TRUE
|101|  4| grp_Carrot|Taker      |grp_Danish |FALSE

第一个表显示了我所期望的结果,但代码生成了第二个表中的值。示例:对于 xID=100,我希望所有者是 grp_Banana,但我的代码返回 grp_Apple。对于 xID=101 我得到了正确的答案,但原因错误。窗口函数似乎采用任何结果集的第一个 yID。

谢谢,非常感谢任何帮助。另外,我愿意不使用窗口函数,这似乎是正确的方向。

最佳答案

除非您的数据库支持ignore nulls 参数,否则这很棘手。您可以使用两个窗口函数来完成此操作:

max(case when yid = yid_special then partnerGroup end) over (partition by xid) as Owner
from (select . . . ,
             min(case when partnerType = 'Giver' and [partnerAgree] = 'True' then yid
                      when partnerType = 'Impacted' and [partnerAgree] = 'True' then yid
                      when [Stakeholder No#] = 1 and [partnerAgree] <> 'True' then yid
                 end) over (partition by xid) as yid_special

您也可以使用 first_value() 编写此代码:

first_value(partnerGroup) over
    (partition by xid
     order by (case when partnerType = 'Giver' and [partnerAgree] = 'True' then yid
                    when partnerType = 'Impacted' and [partnerAgree] = 'True' then yid
                    when [Stakeholder No#] = 1 and [partnerAgree] <> 'True' then yid
                    else 999999
                end) 
    ) as owner

关于SQL - 使用窗口和 case 语句展平表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55344650/

相关文章:

sql - INSERT 语句与 FOREIGN KEY 约束冲突 - SQL Server

sql - 有条件地重置 row_number

sql-server - SQL Server 将十六进制 varchar 值转换为 INT

sql - “Case 语句”可以安全地用于 JDBC 的常规/准备语句中吗?

android - 单击时更改 MenuItem 可见性

mysql - 仅当同一字段中的另一个值不存在时,如何才能在 MySQL 中显示该字段值? IF/ELSEIF 还是 CASE?

sql - 根据关系表获取多个表的结果

mysql - 如何从表中选择所有内容并从另一个表中选择其匹配项?

sql - 列插入或更新与先前的 CREATE RULE 语句施加的规则冲突

sql-server - 可以在 sql server 脚本中嵌入 blob 数据吗?