表B包含计划值。表M保持实际值。我需要找到表B中的所有行,其中表M中没有实际值(即已连接)行,或者连接行具有不同的总实际值行。我正在尝试外部联接和sum ... group by的组合来实现这一点,但它不起作用,因为表B中的“孤儿”没有被返回。
我的查询是: -
SELECT B.Id, B.Date, b.Ref,SUM(M.Actual_Volume), SUM(B.Planned_Volume),
SUM(M.Actual_Value),SUM(B.Planned_Value)
FROM
TableB B
left JOIN TableM M on M.Id = B.Id
inner JOIN TableX on TableX.FieldX = B.FieldX
WHERE TableX.FieldY = (SELECT T.FieldY from TableX T where T.FieldX = 408344)
AND TableX.FieldZ = (SELECT T1.FieldZ from TableX T1 where T1.FieldX = 408344)
group by B.Id, B.Date, B.Ref
having SUM(M.Actual_Volume) <> SUM(B.Planned_Volume)
OR SUM(M.Actual_Value) <> SUM(B.Planned_Value)
order by b.Id
如果我使用=而不是&lt;&gt;比较实际和计划我得到加入的行,但我需要实际不等于计划的行,或者有计划但不是实际的行。
谢谢!
Table B
Id planned_vol planned val
19 2 350
28 1 100
53 3 650
61 1 50
Table M
M.Id B.Id actual_vol actual_val
58 19 2 350
65 28 1 100
66 53 1 150
所以查询应该返回,
B.Id
53 (because planned_vol <> actual_vol and planned_val <> actual_val)
61 (because B.Id 61 is not in table M)
HTH!
答案 0 :(得分:1)
这是未经测试的,但我认为您需要将有要求转移到左外连接要求中。使用CTE(即您需要使用SQL Server 2005或更高版本才能实现此功能)是一种方法。
您的having子句强制SQL Server将B-M连接视为内连接。可能有一种替代方法不使用CTE来检查所有正确位置的NULL。但我更喜欢分而治之的方法。
WITH
[BAlt] AS
(
SELECT
[B].[Id],
[B].[Date],
[B].[Ref],
SUM([B].[Planned_Volume]) AS [Planned_Volume],
SUM([B].[Planned_Value]) AS [Planned_Value],
FROM [TableB] AS [B]
INNER JOIN [TableX] AS [X1] ON [X1].[FieldX] = [B].[FieldX]
AND [X1].[FieldY] =
(
SELECT
[X2].[FieldY]
FROM [TableX] AS [X2]
WHERE [X2].[FieldX] = 408344
)
AND [X1].[FieldZ] =
(
SELECT
[X3].[FieldZ]
FROM [TableX] AS [X2]
WHERE [X3].[FieldX] = 408344
)
GROUP BY
[B].[Id],
[B].[Date],
[B].[Ref]
),
[MAlt] AS
(
SELECT
[M].[Id],
SUM([M].[Actual_Volume]) AS [Actual_Volume],
SUM([M].[Actual_Value]) AS [Actual_Value]
FROM [M]
GROUP BY
[M].[Id]
)
SELECT
[BAlt].[Id],
[BAlt].[Date],
[BAlt].[Ref],
[BAlt].[Planned_Volume],
[BAlt].[Planned_Value],
[MAlt].[Actual_Volume],
[MAlt].[Actual_Value]
FROM [BAlt]
LEFT OUTER JOIN [MAlt] ON [MAlt].[Id] = [BAlt].[Id]
AND
(
[MAlt].[Actual_Volume] <> [BAlt].[Planned_Volume]
OR [MAlt].[Actual_Value] <> [BAlt].[Planned_Value]
)
ORDER BY
[BAlt].[Id]
答案 1 :(得分:0)
我真的没有看到问题:
create table b
( B_id int
,PlannedVolume int
,PlannedValue int
)
create table M
( M_id int
,B_id int
,ActualVolume int
,ActualValue int
)
insert b (b_id, PlannedVolume, PlannedValue)
values (19, 2, 350),
(28, 1, 100),
(53, 3, 650),
(61, 1, 50)
insert m (m_id, b_id, ActualVolume, ActualValue)
values (58, 19, 2, 350),
(65, 28, 1, 100),
(66, 53, 1, 150),
(67, 53, 1, 100)
select b.b_id
from b
left join
( select b_id
,sum(ActualVolume) as ActualVolume
,sum(ActualValue) as ActualValue
from m
group by b_id
) m
on m.b_id = b.b_id
where
m.b_id is null
or
(m.ActualValue <> b.PlannedValue and m.ActualVolume <> b.PlannedVolume)