如何将每个唯一记录(基于2列)与另一个表中的每个记录连接起来

时间:2012-03-01 20:31:44

标签: sql sql-server-2005

这有点难以解释,但我会尽我所能。

说我有两张桌子:

Dates(DateColumn datetime)

SomeData(ID1 int,ID2 int,SomeDate datetime)


Dates始终包含以下日期:

1/1/2012
1/2/2012
1/3/2012

SomeData包含与此类似的数据:

ID  ID1 ID2 SomeDate
1   1   4   1/1/2012
2   1   4   1/2/2012
3   2   3   1/1/2012
4   2   3   1/3/2012
6   5   1   1/2/2012

现在,请注意SomeData中的某些行如何具有相同的ID1和ID2组合。还要注意其中一些缺少Dates表中的某些日期。我需要以某种方式将每个组合与Dates表中的每个日期相结合,以找到缺少的日期。

所以在加入时,数据最终会像这样:

ID      ID1 ID2 SomeDate
1       1   4   1/1/2012
2       1   4   1/2/2012
NULL    1   4   1/3/2012 <-- missing from SomeData table

3       2   3   1/1/2012
NULL    2   3   1/2/2012 <-- missing from SomeData table
4       2   3   1/3/2012

NULL    5   1   1/1/2012 <-- missing from SomeData table
6       5   1   1/2/2012
NULL    5   1   1/3/2012 <-- missing from SomeData table

注意每个ID1 + ID2组合如何使用Dates表中的所有日期返回3条记录,并注意每条“缺失”记录如何维护ID1 + ID2组合。知道如何解决这个问题吗?

提前致谢!

2 个答案:

答案 0 :(得分:3)

SELECT 
    sd.ID,
    ids.ID1,
    ids.ID2,
    d.DateColumn AS SomeDate
FROM
(
    SELECT DISTINCT ID1, ID2
    FROM SomeData
) ids CROSS JOIN
Dates d LEFT JOIN
SomeData sd 
    ON sd.ID1 = ids.ID1 
    AND sd.ID2 = ids.ID2 
    AND sd.SomeDate = d.DateColumn

答案 1 :(得分:1)

CROSS JOIN是你的朋友。这是一个完整的例子

DECLARE @Dates TABLE (DateColumn DATETIME)
INSERT @Dates VALUES ('20120101'), ('20120102'), ('20120103')

DECLARE @SomeData TABLE (ID INTEGER IDENTITY(1,1), ID1 INTEGER, ID2 INTEGER, 
    SomeDate DATETIME)
INSERT @SomeData VALUES (1,4,'20120101'),(1,4,'20120102'),(2,3,'20120101'),
    (2,3,'20120103'), (5,1,'20120102')


SELECT sd2.ID, sd1.ID1, sd1.ID2, d.DateColumn
FROM
(
    SELECT ID1, ID2
    FROM @SomeData
    GROUP BY ID1, ID2
) sd1
    CROSS JOIN @Dates d
    LEFT JOIN @SomeData sd2 ON sd1.ID1 = sd2.ID1 
            AND sd1.ID2 = sd2.ID2 
            AND sd2.SomeDate = d.DateColumn

所以要打破它:

  1. “sd1”子查询获得所有ID1和ID2组合的不同组合
  2. 然后将此日期交叉应用于日期表。结果是,对于每个ID1 + ID2组合,它将导致在日期表中为每个日期返回一行
  3. 最后的LEFT JOIN然后尝试匹配ID1 + ID2 + Date的组合以返回ID值。如果未找到匹配项,则返回NULL作为ID,如果找到则返回ID。