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
但是我在添加 ISNULL
s 和 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
根据@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)
我找到了使用内联的方法 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
我有一个这样的示例查询:
;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
但是我在添加 ISNULL
s 和 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
根据@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)
我找到了使用内联的方法 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