【问题标题】:Compare SQL table to itself to find missing timesheet dates将 SQL 表与其自身进行比较以查找缺失的时间表日期
【发布时间】:2017-04-05 21:34:39
【问题描述】:

下面的 SQL 查询有效,但由于使用了子查询,它需要很长时间才能响应。我希望有人能为我找到优化此查询的方法。

SELECT     a.Userid, a.Date, a.[Total Hrs], a.[Load Date],
                  c.[First Name], c.[Last Name] 
FROM         dbo.TimeSheetReport AS a 
                  INNER JOIN
                  Candidates AS c ON a.Userid = c.Userid 
AND a.Date >= c.[Confirmed Start Date] 
AND (a.Date <= c.[Planned End Date] or c.[Planned End Date] is null)
WHERE a.[Load Date] = @ddlendDate 
AND a.Date not in 
(select b.Date from dbo.TimeSheetReport AS b 
where b.[Load Date] = @ddlstartDate and a.Userid = b.Userid)
AND a.Date < (select MAX(date) from dbo.TimeSheetReport AS c 
where c.[Load Date] = @ddlstartDate)

每个数据子集都是根据数据的加载时间(即加载日期)创建的。它从当前加载 (@ddlendDate) 中查找之前加载 (@ddlstartDate) 中缺少的任何日期。

我尝试在其自身上使用 LEFT OUTER JOIN,但返回的记录为零,我知道它们存在。

有什么想法吗?

【问题讨论】:

    标签: sql sql-server-2008 stored-procedures


    【解决方案1】:

    您可能希望对第一个子查询使用 公用表表达式(有关详细信息,请参阅此链接:https://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx)或临时表。

    第二个可以存储在变量中,不需要定义为子查询(所以只会执行一次)

    declare @MaDate DateTime 
    select @MaDate = MAX([date])  from dbo.TimeSheetReport AS c  where c.[Load Date] = @ddlstartDate
    
    SELECT     a.Userid, a.Date, a.[Total Hrs], a.[Load Date],
                      c.[First Name], c.[Last Name] 
    FROM         dbo.TimeSheetReport AS a 
     INNER JOIN   Candidates AS c ON a.Userid = c.Userid 
            AND a.Date >= c.[Confirmed Start Date] 
            AND (a.Date <= c.[Planned End Date] or c.[Planned End Date] is null)
    WHERE a.[Load Date] = @ddlendDate 
        AND a.Date not in 
            (select b.Date from dbo.TimeSheetReport AS b 
             where b.[Load Date] = @ddlstartDate and a.Userid = b.Userid)
        AND a.Date < @MaDate
    

    【讨论】:

    • 感谢部分解决方案。你的第一个建议不起作用,这个子查询是最需要解决的。第二个看起来很有帮助。
    【解决方案2】:

    将 NOT IN 转换为 NOT EXISTS 将查询执行时间从 12 多分钟减少到 10 秒以下。

    SELECT     a.Userid, a.Date, a.[Total Hrs], a.[Load Date],
                      c.[First Name], c.[Last Name] 
    FROM         dbo.TimeSheetReport AS a 
                      INNER JOIN
                      Candidates AS c ON a.Userid = c.Userid 
    AND a.Date >= c.[Confirmed Start Date] 
    AND (a.Date <= c.[Planned End Date] or c.[Planned End Date] is null)
    WHERE a.[Load Date] = @ddlendDate 
    AND NOT EXISTS (select 1 from dbo.TimeSheetReport AS b 
    WHERE b.[Load Date] = @ddlstartDate AND a.Userid = b.Userid AND a.Date = b.Date)
    AND a.Date < (select MAX(date) from dbo.TimeSheetReport AS c 
    WHERE c.[Load Date] = @ddlstartDate)
    

    【讨论】:

      猜你喜欢
      • 2010-12-25
      • 1970-01-01
      • 2016-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多