La requête SQL ci-dessous fonctionne mais il faut une éternité pour répondre en raison des sous-requêtes utilisées. J'espère que quelqu'un pourra trouver un moyen pour moi d'optimiser cette requête.

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)

Chaque sous-ensemble de données est créé en fonction du moment où les données ont été chargées (c'est-à-dire la date de chargement). Il recherche tous les jours de la charge actuelle (@ddlendDate) qui manquaient lors d'un chargement précédent (@ddlstartDate).

J'ai essayé d'utiliser une jointure externe gauche sur elle-même, mais je ne reçois aucun enregistrement et je sais qu'ils existent.

Des idées?

0
jpollar 6 avril 2017 à 00:34

2 réponses

Meilleure réponse

La conversion de NOT IN en NOT EXISTS a réduit le temps d'exécution de la requête de plus de 12 minutes à moins de 10 secondes.

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)
0
jpollar 6 avril 2017 à 18:50

Vous pouvez utiliser e Common Table Expression (voir ce lien pour plus d'informations: https://technet.microsoft.com/en-us/library/ms190766 (v = sql.105) .aspx) ou une table temporaire pour le première sous-requête.

La seconde peut être stockée dans une variable et n'a pas besoin d'être définie comme une sous-requête (elle ne sera donc exécutée qu'une seule fois)

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
0
Sparrow 5 avril 2017 à 22:01