查询SQL中缺少的行

时间:2014-06-19 14:34:29

标签: tsql sql-server-2012

我们有一个表,每天都有多台计算机上的信息填充。问题是有时它不会从某些计算机中提取信息。

因此,对于一个粗略的例子,表格列将显示为computer_name, information_pulled, qty_pulled, date_pulled

所以让我们说它在一周内每天都会拉,除了15日。查询将拉

Computer_name, Information_pulled, qty_pulled, date_pulled

computer1       infopulled            2           2014-06-14
computer2       infopulled            3           2014-06-14
computer3       infopulled            2           2014-06-14
computer1       infopulled            2           2014-06-15
computer3       infopulled            1           2014-06-15
computer1       infopulled            3           2014-06-16
computer2       infopulled            2           2014-06-16
computer3       infopulled            4           2014-06-16

正如你所看到的,15号计算机2没有任何内容。我希望编写一个查询,以获取特定日期的缺失行。

例如,在运行之后它会显示

computer 2       null           null         20140615

或接近此的任何内容。我们每天早上都试图抓住它,因为这个表没有填充,因为我们可以主动,我不是肯定的,我甚至可以查询丢失的数据,而不是搜索空值。

3 个答案:

答案 0 :(得分:3)

您需要在某处拥有所有计算机的主列表,以便了解计算机何时未计入您的计算机。假设您有一个名为Computer的表来保存它。

声明一个变量来存储您要检查的日期:

declare @date date
set @date = '6/15/2014'

然后您可以查询丢失的行,如下所示:

select c.Computer_name, null, null, @date
from Computer c
where not exists(select 1 
                 from myTable t 
                 where t.Computer_name = c.Computer_name 
                 and t.date_pulled = @date) 

SQL Fiddle

如果您确定每个computer_name已经存在于您的表中至少一次,您可以跳过创建单独的Computer表,并像这样修改查询:

select c.Computer_name, null, null, @date
from (select distinct Computer_name from myTable) c
where not exists(select 1 
                 from myTable t 
                 where t.Computer_name = c.Computer_name 
                 and t.date_pulled = @date)

此查询不够强大,因为它不会显示表中没有行的计算机(例如新计算机或从未将其信息拉出的有问题的计算机)。

答案 1 :(得分:0)

如果你按照日期和computer_name将表连接到自己,如下所示,你应该得到一个缺少日期的列表

SELECT t1.computer_name, null as information_pulled, null as qty_pulled, 
DATEADD(day,1,t1.date_pulled) as missing_date
FROM  computer_info t1
LEFT JOIN computer_info t2 ON t2.date_pulled = DATEADD(day,1,t1.date_pulled) 
      AND t2.computer_name = t1.computer_name
WHERE t1.date_pulled >= '2014-06-14'
  AND t2.date_pulled IS NULL

这也将获得尚未提取的下一个日期,但这应该是明确的,您可以添加一个额外的条件来过滤它。

AND DATEADD(day,1,t1.date_pulled) < '2014-06-17'

当然,这只有在您知道前几天表中已存在的每个计算机名称时才有效。如果没有,@ Jerrad关于创建一个单独的计算机表的建议会有所帮助。

编辑:如果差距大于一天,您可能希望看到

SELECT t1.computer_name, null as info, null as qty_pulled,
       DATEADD(day,1,t1.date_pulled) as missing_date, 
       t3.date_pulled AS next_pulled_date
FROM  computer_info t1
LEFT JOIN computer_info t2 ON t2.date_pulled = DATEADD(day,1,t1.date_pulled) 
      AND t2.computer_name = t1.computer_name
LEFT JOIN computer_info t3 ON t3.date_pulled > t1.date_pulled 
      AND t3.computer_name = t1.computer_name
LEFT JOIN computer_info t4 ON t4.date_pulled > t1.date_pulled 
      AND t4.date_pulled < t3.date_pulled 
      AND t4.computer_name = t1.computer_name
WHERE t1.date_pulled >= '2014-06-14'
  AND t2.date_pulled IS NULL
  AND t4.date_pulled IS NULL
  AND DATEADD(day,1,t1.date_pulled) < '2014-06-17'

&#39; t3&#39;加入将加入第一个缺失的日期和&#39; t4&#39;与t4.pulled_date IS NULL一起加入将排除除这些日期中最低的所有日期之外的所有日期。

您也可以使用子查询执行此操作,但不包括联接在过去很有用。

答案 2 :(得分:0)

我认为交叉加入会解决您的问题。
在下面的查询中,每台计算机必须至少成功上传一次,每天至少上传一次 通过这种方式,您可以获得所有缺少的计算机/日期。

select 
    Compare.* 
from Table_1 T1
    right join (
        select *
        from 
            (select Computer_name from Table_1 group by Computer_name) CPUS,
            (select date_pulled from Table_1 group by date_pulled) DAYs
        ) Compare 
    on T1.Computer_name=Compare.Computer_name 
        and T1.date_pulled=Compare.date_pulled    
where T1.Computer_name is null

希望得到这个帮助。