SQL 服务器:添加 LEFT JOIN 后更改字段的总和

SQL Server : Sum over a field changed after adding a LEFT JOIN

我有一个这样的示例查询:

;WITH view1 AS (
    SELECT 1 AS id, 1 AS pId, 'a' AS pName, 1 AS kind 
    UNION ALL SELECT 2, 1, 'a', 2 
    UNION ALL SELECT 3, 1, 'a', 1 
    UNION ALL SELECT 4, 2, 'b', 2 
    UNION ALL SELECT 5, 2, 'b', 2 
    UNION ALL SELECT 6, 2, 'b', 1 
), view2 AS (
    SELECT 1 AS id, 1 AS pId, 'a' AS pName, 5 AS price
    UNION ALL SELECT 3, 3, 'c', 3 
    UNION ALL SELECT 6, 2, 'b', 3 
)   
SELECT 
    ISNULL(v2.pId, v1.pId) AS pId,
    ISNULL(v2.pName, v1.pName) AS pName,
    SUM(CASE v1.kind WHEN 1 THEN 1 ELSE 0 END) AS countKind1,
    SUM(v2.price) AS sumPrice
FROM 
    view1 v1
    LEFT OUTER JOIN
    view2 v2 ON v1.id = v2.id
GROUP BY
    ISNULL(v2.pId, v1.pId),
    ISNULL(v2.pName, v1.pName)

其结果是:

pId | pName | countKind1 | sumPrice
----+-------+------------+-----------
1   | a     | 1          | 5
2   | b     | 1          | 3 
3   | c     | 1          | 3

但是我在添加 ISNULLs 和 sumPrice 之后想要这个结果:

pId | pName | countKind1 | sumPrice
----+-------+------------+-----------
1   | a     | 2          | 5
2   | b     | 1          | 3 
3   | c     | 0          | 3

您的查询看起来有点奇怪。我可以创建几种获得所需结果的方法,但我不确定您的数据背后的含义是什么。一般来说,我总是建议您尽早对数据进行分组,因此您可能可以对 view1 进行分组,然后按 pId.

加入

这里是给出结果的查询

;WITH view1 AS (
    SELECT 1 AS id, 1 AS pId, 'a' AS pName, 1 AS kind 
    UNION ALL SELECT 2, 1, 'a', 2 
    UNION ALL SELECT 3, 1, 'a', 1 
    UNION ALL SELECT 4, 2, 'b', 2 
    UNION ALL SELECT 5, 2, 'b', 2 
    UNION ALL SELECT 6, 2, 'b', 1 
), view2 AS (
    SELECT 1 AS id, 1 AS pId, 'a' AS pName, 5 AS price
    UNION ALL SELECT 3, 3, 'c', 3 
    UNION ALL SELECT 6, 2, 'b', 3 
), cte1 as (
SELECT 
    ISNULL(v2.pId, v1.pId) AS pId,
    ISNULL(v2.pName, v1.pName) AS pName,
    SUM(v2.price) AS sumPrice
FROM 
    view1 v1
    LEFT OUTER JOIN
    view2 v2 ON v1.id = v2.id
GROUP BY
    ISNULL(v2.pId, v1.pId),
    ISNULL(v2.pName, v1.pName)
), cte2 as (
    select pName, sum(case when kind = 1 then 1 else 0 end) as countKind1
    from view1
    group by pName
)
select
    c1.pId,
    c1.pName,
    isnull(c2.countKind1, 0) as countKind1,
    c1.sumPrice
from cte1 as c1
    left outer join cte2 as c2 on c2.pName = c1.pName

sql fiddle demo

根据@Roman 的评论,您需要加入 pID。 您还需要将 JOIN 更改为 FULL OUTER 连接,因为 view1 没有 'c' 最后,SUM(Price) 看起来不对 - 如果这是每 'each' 的价格,您需要使用不同的聚合,例如 Max:

;WITH view1 AS (
    SELECT 1 AS id, 1 AS pId, 'a' AS pName, 1 AS kind 
    UNION ALL SELECT 2, 1, 'a', 2 
    UNION ALL SELECT 3, 1, 'a', 1 
    UNION ALL SELECT 4, 2, 'b', 2 
    UNION ALL SELECT 5, 2, 'b', 2 
    UNION ALL SELECT 6, 2, 'b', 1 
), view2 AS (
    SELECT 1 AS id, 1 AS pId, 'a' AS pName, 5 AS price
    UNION ALL SELECT 3, 3, 'c', 3 
    UNION ALL SELECT 6, 2, 'b', 3 
)   
SELECT 
    ISNULL(v2.pId, v1.pId) AS pId,
    ISNULL(v2.pName, v1.pName) AS pName,
    SUM(CASE WHEN v1.kind = 1 THEN 1 ELSE 0 END) AS countKind1,
    MAX(v2.price) AS maxPrice
FROM 
    view1 v1
    FULL OUTER JOIN
    view2 v2 ON v1.pid = v2.pid
GROUP BY
    ISNULL(v2.pId, v1.pId),
    ISNULL(v2.pName, v1.pName)

SqlFiddle here

我找到了使用内联的方法 select:

SELECT 
    ISNULL(v2.pId, v1.pId) AS pId,
    ISNULL(v2.pName, v1.pName) AS pName,
    (SELECT COUNT(*) FROM view1 vi WHERE vi.kind = 1 AND vi.pId = ISNULL(v2.pId, v1.pId)) AS countKind1,
    SUM(v2.price) AS sumPrice
FROM 
    view1 v1
    LEFT OUTER JOIN
    view2 v2 ON v1.id = v2.id
GROUP BY
    ISNULL(v2.pId, v1.pId),
    ISNULL(v2.pName, v1.pName)

还有这个:

SELECT 
    ISNULL(v2.pId, v1.pId) AS pId,
    ISNULL(v2.pName, v1.pName) AS pName,
    ISNULL(tc.Counts, 0) AS countKind1,
    SUM(v2.price) AS sumPrice
FROM 
    view1 v1
    LEFT OUTER JOIN
    view2 v2 ON v1.id = v2.id
    LEFT OUTER JOIN
    (SELECT vi.pId, COUNT(*) Counts FROM view1 vi WHERE vi.kind = 1 GROUP BY vi.pId) AS tc ON tc.pId = ISNULL(v2.pId, v1.pId)
GROUP BY
    ISNULL(v2.pId, v1.pId),
    ISNULL(v2.pName, v1.pName),
    tc.Counts