SQL返回缺少的行

时间:2014-03-22 07:02:58

标签: sql

我有一个场景,我需要使用SQL在Table中查找缺少的记录 - 不使用Cursor,Views,SP。

  • 对于特定的CustID,初始Start_Date为19000101,End_date为任意随机日期。
  • 然后,对于同一个CustID的下一个记录,其Start_Date将为End_Date(上一记录)+ 1。
  • 其End_Date将再次为任意日期。
  • 依此类推......
  • 对于相同CustID的最后记录,其结束日期为99991231。

以下数据将更好地解释它。

CustID  Start_Date  End_Date
1   19000101    20121231
1   20130101    20130831
1   20130901    20140321
1   20140321    99991231

基本上我试图在SCD2场景中填充数据。

现在我想找到丢失的记录(或CustID)。

如下所示,我们没有CustID = 4Start_Date = 20120606End_Date = 20140101

的记录
CustID  Start_Date  End_Date
4   19000101    20120605
4   20140102    99991231

创建表的代码

CREATE TABLE TestTable
(
  CustID int,
  Start_Date int,
  End_Date int
)

INSERT INTO TestTable values (1,19000101,20121231)
INSERT INTO TestTable values (1,20130101,20130831)
INSERT INTO TestTable values (1,20130901,20140321)
INSERT INTO TestTable values (1,20140321,99991231)

INSERT INTO TestTable values (2,19000101,99991213)

INSERT INTO TestTable values (3,19000101,20140202)
INSERT INTO TestTable values (3,20140203,99991231)
INSERT INTO TestTable values (4,19000101,20120605)
--INSERT INTO TestTable values (4,20120606,20140101)   --Missing Value
INSERT INTO TestTable values (4,20140102,99991231)

现在SQL应该返回CustID = 4,因为它缺少值。

3 个答案:

答案 0 :(得分:2)

我的想法是基于这种逻辑。让我们假设19000101为1,99991231为10.现在对于所有ID,如果减去End_date - start_date并将它们相加,则总和必须等于9(10 - 1)。你可以在这里做同样的事情

SELECT ID, SUM(END_DATE - START_DATE) as total from TABLE group by ID where total < (MAX_END_DATE - MIN_START_DATE)

您可能希望在SQL中找到命令,该命令提供2天之间的天数,并在SUM部分中使用该命令。

让我们采取以下示例

1 1900 2003
1 2003 9999
2 1900 2222
2 2222 9977
3 1900 9999

查询将按如下方式执行

1 (2003 - 1900) + (9999 - 2003) = 1 8098
2 (2222 - 1900) + (9977 - 2222) = 2 9077
3 (9999 - 1900) = 3 8098

where子句将消除1和3,只给你2,这就是你想要的。

答案 1 :(得分:0)

如果您只需要CustID,那么这将完成

SELECT t1.CustID
FROM TestTable t1
LEFT JOIN TestTable t2
ON DATEADD(D, 1, t1.Start_Date) = t2.Start_Date
WHERE t2.CustID IS NULL
GROUP BY t1.CustID

答案 2 :(得分:0)

如果满足以下条件之一,则需要行:

  1. 不是最后一行(99991231)且没有匹配的下一行
  2. 不是开始行(19000101)且没有匹配上一行
  3. 您可以将联接保留到同一个表中以查找上一行和下一行,并通过检查列值为null来过滤未找到行的结果:

    SELECT t1.CustID, t1.StartDate, t1.EndDate
    FROM TestTable t1
    LEFT JOIN TestTable tPrevious on tPrevious.CustID = t1.CustID
        and tPrevious.EndDate = t1.StartDate - 1
    LEFT JOIN TestTable tNext on tNext.CustID = t1.CustID
        and tNext.StartDate = t1.EndDate + 1
    WHERE (t1.EndDate <> 99991231 and tNext.CustID is null) -- no following
        or (t1.StartDate <> 19000101 and tPrevious.CustID is null) -- no previous