2012-04-02 3 views
0

표 B에는 계획된 값이 있습니다. 표 M은 실제 값을 유지합니다. 테이블 B에서 모든 행을 찾아야하는데, 여기에는 테이블 M에 실제 값 (즉, 조인 된 행)이 있거나 조인 된 행의 총 실제 값 행이 서로 다른 경우가 있습니다. 달성하기 위해 외부 조인과 합계 ... 그룹을 조합하려고 시도하지만 테이블 B의 '고아'가 반환되지 않기 때문에 작동하지 않습니다. 나는 실제 데이터를 비교하고 가입하고 난 행을 얻을 계획하기> = 대신 <으로 사용하는 경우왼쪽 가입/합계가있는 SQL Server/

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 

,하지만 난 실제 데이터가 계획과 동일하지 않는 행을 필요 - :

내 쿼리입니다 , 또는 계획된 것이지만 실제는없는 곳.

감사합니다.

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!

+3

당신이하지 않는 일부 샘플은 (모두 이유) 반환 할 행의 데이터 및 적어도 하나 개의 행을 보여 주시겠습니까 돌려주고 싶다. –

+0

빠른 수정은 'SUM (M.Actual_Volume) is null 또는 SUM (M.Actual_Value) is null'을 having 절에 추가하는 것이지만 n : m 관계의 양측을 합산하려고한다고 생각합니다. 데이터 복제가 종료됩니다. M과 B 사이의 스키마와 관계에 대한 정보를 더 게시 할 수 있습니까? –

+0

예, TableB to TableM은 m : m 정의 테이블이 TableX이기 때문에 – epx

답변

1

이것은 테스트되지 않았지만 요구 사항을 왼쪽 외부 조인 요구 사항으로 옮겨야한다고 생각합니다. 이 작업을 수행하려면 CTE (즉, SQL Server 2005 이상을 사용해야 함)를 사용하는 것이 한 가지 방법입니다.

귀하의 having 절은 SQL Server에서 B-M 조인을 내부 조인으로 처리하도록하고 있습니다. 모든 올바른 위치에서 NULL을 확인하는 CTE를 사용하지 않는 대체 접근 방식이있을 수 있습니다. 그러나 저는 분단하고 정복하는 방법을 선호합니다.

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] 
정말 문제가 표시되지 않습니다
+0

SQL Server 2005 9.00.1399.06을 사용하고 있으므로이 방법을 시도합니다. – epx

+0

Daniel,이 방법을 사용하면 올바른 SELECT가 SELECT 절로 선택되지만 어떤 이유로 최종 SELECT가 올바르게 결합되지 않고 NULL을 반환합니다. Actual_Volume 및 Actual_Value 필드는 고칠 방법에 대한 생각? – epx

+0

@epx ID가 'B'에는 있지만 M에는없는 경우 Actual_Volume 및 Actual_Value는 null이됩니다. 기본값 (예 : 0이면,'ISNULL ([MAlt]. [Actual_Volume], 0)'을 사용하고 최종 select 절에서'Actual_Value'와 동일합니다. –

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) 
+0

문제는 b와 m 사이에 1 : 1이 아니므로 m에서 67,53,1,100 행을 가질 수도 있습니다. 그래서 지금 b_id 53에 대해 우리는 현재 1의 걸출한 plans_volume과 400의 걸출한 plans_value를 가지고 있습니다. 그래서 나는 GROUP BY ... SUM을 가지고 있지만 아직 없습니다 :-( – epx

+0

나는 업데이트 된 코멘트입니다. 봐. – zejafo