SQL Server中带有case语句的更新查询中的聚合函数

时间:2018-08-21 06:53:43

标签: sql sql-server

我正在尝试使用聚合函数和case语句编写更新查询。 一些我被困住的方式

最初,我写了以下查询,给了我错误tha,“聚合函数不能用于更新语句

UPDATE report
SET report.LoadDischargeQty = 
CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'D' AND cargo.CRG_Quantity is NOT NULL THEN cargo.CRG_Quantity 
 ELSE
     CASE WHEN report.PlaId = 'LP' THEN 
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'D' THEN ISNULL(SUM(CRG_SFgrMT),0) END -  
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'A' THEN ISNULL(SUM(CRG_SFgrMT),0)END 
         WHEN report.PlaId = 'DP' THEN 
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'A' THEN ISNULL(SUM(CRG_SFgrMT),0) END-
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'D' THEN ISNULL(SUM(CRG_SFgrMT),0)END
        ELSE 0 END  
END 
from #CargoPerformanceReport report
INNER JOIN POSCARGO cargo ON cargo.POS_ID = report.PositionId AND ISNULL(cargo.CRG_Deleted,0)=0

所以我将其重构如下

UPDATE report
SET report.LoadDischargeQty = 
CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'D' AND cargo.CRG_Quantity is NOT NULL THEN cargo.CRG_Quantity 
 ELSE
    select quantity.dischargeQuantity from (SELECT CASE WHEN report.PlaId = 'LP' THEN 
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'D' THEN ISNULL(SUM(CRG_SFgrMT),0) END -  
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'A' THEN ISNULL(SUM(CRG_SFgrMT),0)END 
         WHEN report.PlaId = 'DP' THEN 
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'A' THEN ISNULL(SUM(CRG_SFgrMT),0) END-
                                    CASE WHEN SUBSTRING(CRG_ArrDep,1,1) = 'D' THEN ISNULL(SUM(CRG_SFgrMT),0)END
        ELSE 0 END  dischargeQuantity ) quantity
END 
from #CargoPerformanceReport report
INNER JOIN POSCARGO cargo ON cargo.POS_ID = report.PositionId AND ISNULL(cargo.CRG_Deleted,0)=0

表结构

CREATE TABLE #CargoPerformanceReport
(
    PositionId              VARCHAR(12),
    PortAndActivityName     VARCHAR(100),
    PlaId                   VARCHAR(12),
    LoadDischargeQty            REAL,

);

插入#CargoPerformanceReport 值('100',null,'LP',null)

CREATE TABLE #Poscargo
(
    POS_ID              VARCHAR(12),
    CRG_ArrDep          VARCHAR(3),
    CRG_SFgrMT          REAL,
    CRG_Quantity        REAL,
    CRG_Deleted         BIT
);


Insert Into #Poscargo(POS_ID,CRG_ArrDep,CRG_SFgrMT,null,0)
Values ('100','DD',100)

Insert Into #Poscargo(POS_ID,CRG_ArrDep,CRG_SFgrMT)
Values ('100','AD',100)

Insert Into #Poscargo(POS_ID,CRG_ArrDep,CRG_SFgrMT)
Values ('100','DD',200)

Insert Into #Poscargo(POS_ID,CRG_ArrDep,CRG_SFgrMT)
Values ('100','AD',50)


Insert Into #Poscargo(POS_ID,CRG_ArrDep,CRG_SFgrMT)
Values ('101','DL',200)


Insert Into #Poscargo(POS_ID,CRG_ArrDep,CRG_SFgrMT)
Values ('101','AL',200)

SELECT * FROM #Poscargo
SELECT * FROM #CargoPerformanceReport

结果:-

PositionId |    PlaId | LoadDischargeQty
100        |     LP   | 150

但这不是正确的方法,并且也有错误。

有人为它优化了解决方案吗?

2 个答案:

答案 0 :(得分:1)

将所有内容放入子查询:

SELECT LoadDischargeQty = 
  CASE 
    WHEN report.PlaId = 'LP' 
    THEN 1 
    ELSE -1 
  END * cargo.qty
FROM CargoPerformanceReport report
CROSS APPLY(
  SELECT SUM(
    CASE 
      WHEN CRG_ArrDep LIKE 'D%' 
      THEN 1 
      WHEN CRG_ArrDep LIKE 'A%' 
      THEN -1 
      ELSE 0
    END * ISNULL(CRG_SFgrMT, 0)
    ) qty
  FROM POSCARGO cargo
  WHERE cargo.POS_ID = report.PositionId 
    AND ISNULL(cargo.CRG_Deleted,0)=0
) cargo

https://docs.google.com/forms/d/e/1FAIpQLSdDTzjZaT1OC03bRr7cxAladJ49m8AJqovuaXUClBuIfyECqA/viewform?usp=sf_link

我不知道应该如何使用CRG_Quantity列,并且您没有向该行提供任何数据,因此我将其删除以向您显示聚合本身。工作正常,您将得到150。您可以轻松地将其转换为update语句。

答案 1 :(得分:1)

也许是这样吗?
它使用具有汇总案例的案例。

在SQL Fiddle here上进行测试

UPDATE t
SET LoadDischargeQty = q.CalcDischargeQty
FROM #CargoPerformanceReport t
JOIN
(
    SELECT report.PositionId, report.PlaId,
    CASE 
    WHEN SUM(CASE WHEN LEFT(cargo.CRG_ArrDep,1) = 'D' THEN cargo.CRG_Quantity END) IS NOT NULL 
    THEN SUM(CASE WHEN LEFT(cargo.CRG_ArrDep,1) = 'D' THEN cargo.CRG_Quantity END)
    ELSE CASE 
         WHEN report.PlaId = 'LP' 
         THEN SUM(CASE WHEN LEFT(cargo.CRG_ArrDep,1) = 'D' THEN cargo.CRG_SFgrMT END) -  
              SUM(CASE WHEN LEFT(cargo.CRG_ArrDep,1) = 'A' THEN cargo.CRG_SFgrMT END) 
         WHEN report.PlaId = 'DP' 
         THEN SUM(CASE WHEN LEFT(cargo.CRG_ArrDep,1) = 'A' THEN cargo.CRG_SFgrMT END) -  
              SUM(CASE WHEN LEFT(cargo.CRG_ArrDep,1) = 'D' THEN cargo.CRG_SFgrMT END) 
         ELSE 0
         END
    END AS CalcDischargeQty
    FROM #CargoPerformanceReport report
    INNER JOIN #Poscargo cargo 
       ON cargo.POS_ID = report.PositionId AND (cargo.CRG_Deleted = 0 OR cargo.CRG_Deleted IS NULL)
    GROUP BY report.PositionId, report.PlaId
) q ON t.PositionId = q.PositionId;

样本数据

IF OBJECT_ID('tempdb..#CargoPerformanceReport') IS NOT NULL DROP TABLE #CargoPerformanceReport;
CREATE TABLE #CargoPerformanceReport
(
    PositionId          VARCHAR(12) PRIMARY KEY,
    PortAndActivityName VARCHAR(100),
    PlaId               VARCHAR(12),
    LoadDischargeQty    REAL
);

IF OBJECT_ID('tempdb..#Poscargo') IS NOT NULL DROP TABLE #Poscargo;
CREATE TABLE #Poscargo
(
    POS_ID       VARCHAR(12),
    CRG_ArrDep   VARCHAR(3),
    CRG_SFgrMT   REAL,
    CRG_Quantity REAL,
    CRG_Deleted  BIT
);

Insert into #CargoPerformanceReport Values 
('100','name1','LP',null),
('101','name2','DP',null),
('102','name3','DP',null);

Insert Into #Poscargo(POS_ID, CRG_ArrDep, CRG_SFgrMT, CRG_Quantity, CRG_Deleted) Values 
 ('100','DD',100,null,0)
,('100','AD',100,null,0)
,('100','DD',200,null,0)
,('100','AD',50,null,0)
,('101','DL',100,null,0)
,('101','AL',200,null,0)
,('102','DL',100,500,0)
,('102','AL',200,null,0);

结果

PositionId PortAndActivityName PlaId LoadDischargeQty
---------- ------------------- ----- ----------------
100        name1               LP    150
101        name2               DP    100
102        name3               DP    500