SQL Server SUM IF 使用具有多个条件的窗口函数

Posted

技术标签:

【中文标题】SQL Server SUM IF 使用具有多个条件的窗口函数【英文标题】:SQL Server SUM IF using Window function with multiple conditions 【发布时间】:2020-09-01 10:50:05 【问题描述】:

编辑:原始问题名称“SQL Server SUM 记录仅按某些值分组”。精致,因为现在知道要寻找什么。

我目前正在尝试使用OVERPARITION BY 根据条件进行聚合,但是我不知道如何整合最后一个条件。

它应该做什么: 如果每个CONTRACTIDVALIDFROMVALIDTORENTALCOSTTYPEID 列中有一个值“H104” 然后聚合所有AMOUNT 具有以“H”开头的RENTALCOSTTYPEID 值。 ELSE 显示 AMOUNT 而不进行聚合。

我当前的代码在CONTRACTIDVALIDFROMVALIDTO 有一个值“H104”时有效。但是,如果每个 CONTRACTIDVALIDFROMVALIDTO 没有值 'H104' 它给出 '0' 而不是 AMOUNT 查看代码,它显然输入了“0”,但如果我更改此值,它会与值为“H104”的字段混淆。如何将这个条件集成到以下代码中?

SELECT
CONTRACTID
,RENTALCOSTTYPEID
,VALIDFROM
,VALIDTO
,AMOUNT
,CASE 
    WHEN RENTALCOSTTYPEID = 'H104' 
    THEN SUM(CASE WHEN RENTALCOSTTYPEID LIKE 'H%' THEN AMOUNT ELSE 0  END) OVER (PARTITION BY CONTRACTID, VALIDFROM, VALIDTO) 
    ELSE SUM(CASE WHEN RENTALCOSTTYPEID LIKE 'H%' THEN 0 ELSE AMOUNT  END) OVER (PARTITION BY RENTALCOSTTYPEID, CONTRACTID, VALIDFROM, VALIDTO)
END AS TESTCOLUMN
FROM PMCCONTRACTLINE

CURRENT 列包含我目前的结果

ENDRESULT 列包含我想要的结果

+------------+------------------+------------+------------+---------+---------+-----------+
| CONTRACTID | RENTALCOSTTYPEID | VALIDFROM  | VALIDTO    | AMOUNT  | CURRENT | ENDRESULT |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC018453   | H104             | 2020-07-01 | 2021-01-01 | 775.08  | 446.72  | 446.72    |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC018453   | H110             | 2020-07-01 | 2021-01-01 | -328.36 | 0.00    | 0.00      |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC018453   | V446             | 2020-07-01 | 2021-01-01 | 48.00   | 48.00   | 48.00     |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC055533   | H105             | 2020-07-01 | 2021-01-01 | 330.00  | 0.00    | 330.00    |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC055533   | H105H            | 2019-07-01 | 2020-06-30 | 330.00  | 0.00    | 330.00    |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC103696   | H104             | 2020-06-03 | 2021-01-01 | 867.00  | 867.00  | 867.00    |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC103696   | S468             | 2020-06-03 | 2021-01-01 | 2.00    | 2.00    | 2.00      |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC103696   | S484             | 2020-06-03 | 2021-01-01 | 1.00    | 1.00    | 1.00      |
+------------+------------------+------------+------------+---------+---------+-----------+
| HC103696   | S488             | 2020-06-03 | 2021-01-01 | 0.50    | 0.50    | 0.50      |
+------------+------------------+------------+------------+---------+---------+-----------+

【问题讨论】:

您可以尝试将您的查询用作子查询并添加一个列,例如CASE WHEN costtype = N'H107' THEN amount ELSE 0 END AS amountH107,然后创建一个查询和SUM 这个新列... 您可以在聚合函数中添加case 表达式。看到这个similar question。 我快到了。编辑了我的帖子(见下文)。以下代码几乎可以满足我的所有需求:CASE WHEN C.RENTALCOSTTYPEID = 'H104' THEN SUM(CASE WHEN C.RENTALCOSTTYPEID LIKE 'H%' THEN C.AMOUNT ELSE 0 END) OVER (PARTITION BY C.CONTRACTID, C.VALIDFROM, C.VALIDTO) ELSE SUM(C.RENTALCOSTTYPEID LIKE 'H%' THEN 0 ELSE c.amount END) OVER (Partition by C.RENTALCOSTTYPEID, C.CONTRACTID, C.VALIDFROM, C.VALIDTO) END AS TESTCOLUMN跨度> 为什么前三行有不同的ENDRESULT?他们有相同的CONTRACTIDVALIDFROMVALIDTO,而且他们在RENTALCOSTTYPEID 列中有一个“H104”不应该都是 446.72? 【参考方案1】:

您正试图在同一行显示聚合值和非聚合值。虽然在单个 select 语句中实现这一点可能是可能的,但在一个查询中组合几个 select 会更容易。

例如,如果您计算rentalcosttypeid H% 行的总和,其中H104 行在common table expression (CTE) 中,那么您可以稍后加入这些结果。

样本数据

declare @PMCCONTRACTLINE table
(
    CONTRACTID nvarchar(10),
    RENTALCOSTTYPEID nvarchar(5),
    VALIDFROM date,
    VALIDTO date,
    AMOUNT money
);

insert into @PMCCONTRACTLINE (CONTRACTID, RENTALCOSTTYPEID, VALIDFROM, VALIDTO, AMOUNT) values
('HC018453', 'H104',  '2020-07-01', '2021-01-01', 775.08 ),
('HC018453', 'H110',  '2020-07-01', '2021-01-01', -328.36),
('HC018453', 'V446',  '2020-07-01', '2021-01-01', 48.00  ),
('HC055533', 'H105',  '2020-07-01', '2021-01-01', 330.00 ),
('HC055533', 'H105H', '2019-07-01', '2020-06-30', 330.00 ),
('HC103696', 'H104',  '2020-06-03', '2021-01-01', 867.00 ),
('HC103696', 'S468',  '2020-06-03', '2021-01-01', 2.00   ),
('HC103696', 'S484',  '2020-06-03', '2021-01-01', 1.00   ),
('HC103696', 'S488',  '2020-06-03', '2021-01-01', 0.50   );

解决方案

cte_SumH104 定义为H% 行的结果集,其中H104 行用于相同的ContractID。

with cte_SumH104 as
(
    select cl.CONTRACTID, sum(cl.AMOUNT) as 'SUMH'
    from @PMCCONTRACTLINE cl
    where cl.RENTALCOSTTYPEID like 'H%'
      and exists (  select top 1 'x'
                    from @PMCCONTRACTLINE clh104
                    where clh104.CONTRACTID = cl.CONTRACTID
                      and clh104.RENTALCOSTTYPEID = 'H104' )
    group by cl.CONTRACTID
)
select  cl.*,
        s.SUMH,
        case
            when cl.RENTALCOSTTYPEID = 'H104' then s.SUMH
            when cl.RENTALCOSTTYPEID like 'H%' and s.SUMH is not null then 0
            else cl.AMOUNT
        end as 'TEST'
from @PMCCONTRACTLINE cl
left join cte_SumH104 s
    on s.CONTRACTID = cl.CONTRACTID;

结果

CONTRACTID  RENTALCOSTTYPEID  VALIDFROM   VALIDTO     AMOUNT    SUMH     TEST
----------- ----------------- ----------- ----------- --------- -------- --------
HC018453    H104              2020-07-01  2021-01-01  775,08    446,72   446,72
HC018453    H110              2020-07-01  2021-01-01  -328,36   446,72   0,00
HC018453    V446              2020-07-01  2021-01-01  48,00     446,72   48,00
HC055533    H105              2020-07-01  2021-01-01  330,00    NULL     330,00
HC055533    H105H             2019-07-01  2020-06-30  330,00    NULL     330,00
HC103696    H104              2020-06-03  2021-01-01  867,00    867,00   867,00
HC103696    S468              2020-06-03  2021-01-01  2,00      867,00   2,00
HC103696    S484              2020-06-03  2021-01-01  1,00      867,00   1,00
HC103696    S488              2020-06-03  2021-01-01  0,50      867,00   0,50

【讨论】:

以上是关于SQL Server SUM IF 使用具有多个条件的窗口函数的主要内容,如果未能解决你的问题,请参考以下文章

SQL中多分支If语句的性能(Sql Server 2008)

ms sql server字符串与另一个具有多个值的字符串进行比较

使用JPA在Sql中具有不同值的多个语句where子句

SQL Server:使用具有相同 OVER 子句的多个聚合/分析函数?

无法从具有多个 SQL Server 版本的 SQL Server 读取 Excel 文件

具有多个或条件的sql server外连接