相关子查询中的EXISTS和NOT EXISTS

时间:2014-06-26 15:17:36

标签: sql sql-server exists correlated-subquery

我一直在努力研究如何在一天左右的时间内完成特定查询,并且已经达到了我需要一些外界帮助的程度。因此我的问题。

鉴于以下数据;

DECLARE @Data AS TABLE
(
      OrgId INT,
      ThingId INT
)

DECLARE @ReplacementData AS TABLE
(
      OldThingId INT,
      NewThingId INT
)

INSERT INTO @Data (OrgId, ThingId)
VALUES (1, 2), (1, 3), (1, 4),
       (2, 1), (2, 4),
       (3, 3), (3, 4)

INSERT INTO @ReplacementData (OldThingId, NewThingId)
VALUES (3, 4), (2, 5)

我想找到任何有"事情的组织"已被替换为@ReplacementData表变量中的表示。我想要看到组织ID,它们已被替换的东西以及应该替换它的东西的id。例如,鉴于上述数据,我应该看到;

Org id, Thing Id, Replacement Thing Id org doesn't have but should have 
1, 2, 5 -- As Org 1 has 2, but not 5

我试图让这项工作有很多尝试,而我似乎无法理解如何解决这个问题。以下是我的几次尝试,但我认为我离开了;

-- Attempt using correlated subqueries and EXISTS clauses
-- Show all orgs that have the old thing, but not the new thing
-- Ideally, limit results to OrgId, OldThingId and the NewThingId that they should now have too
SELECT *
  FROM @Data d
 WHERE EXISTS (SELECT *
                 FROM @Data oldstuff
                WHERE oldstuff.OrgId = d.OrgId
                  AND oldstuff.ThingId IN
                (SELECT OldThingID
                   FROM @ReplacementData))
   AND NOT EXISTS (SELECT *
                 FROM @Data oldstuff
                WHERE oldstuff.OrgId = d.OrgId
                  AND oldstuff.ThingId IN
                (SELECT NewThingID
                   FROM @ReplacementData))


   -- Attempt at using a JOIN to only include those old things that the org has (via the where clause)
   -- Also try exists to show missing new things. 
   SELECT *
      FROM @Data d
 LEFT JOIN @ReplacementData rd ON rd.OldThingId = d.ThingId
     WHERE NOT EXISTS (
            SELECT *
              FROM @Data dta
        INNER JOIN @ReplacementData rep ON rep.NewThingId = dta.ThingId
             WHERE dta.OrgId = d.OrgId
    )
   AND rd.OldThingId IS NOT NULL

非常感谢任何帮助。我可能会完全错误,所以如果有更好的方法来解决这类问题,请告诉我。

1 个答案:

答案 0 :(得分:2)

试试看,告诉我。

DECLARE @Data AS TABLE
(
      OrgId INT,
      ThingId INT
)

DECLARE @ReplacementData AS TABLE
(
      OldThingId INT,
      NewThingId INT
)

INSERT INTO @Data (OrgId, ThingId)
VALUES (1, 2), (1, 3), (1, 4),
       (2, 1), (2, 4),
       (3, 3), (3, 4)

INSERT INTO @ReplacementData (OldThingId, NewThingId)
VALUES (3, 4), (2, 5)

SELECT D.OrgId, RD.*
FROM @Data D 
JOIN @ReplacementData RD
   ON D.ThingId=RD.OldThingId
   LEFT OUTER JOIN @Data EXCLUDE
      ON D.OrgId = EXCLUDE.OrgId
      AND RD.NewThingId = EXCLUDE.ThingId
WHERE EXCLUDE.OrgId IS NULL