2010-08-13 10 views
1

J'ai le SQL suivant qui obtient une saison pour chaque jour dans une plage de dates, puis groupes chaque saison par date de début et de fin avec le nombre de nuits. Ce qu'il fait n'est pas important mais ma question est de savoir quelle est la meilleure, la façon dont je l'ai fait ci-dessous ou utiliser la première instruction select comme sous-requête chaque fois que @dateSeasons est utilisé dans la deuxième requête. Les deux façons semblent fonctionner de la même manière, mais cette façon semble plus propre.Joints multiples sur une table temporaire OU sous-requête dans SQL 2008

DECLARE @dateSeasons TABLE ([date] date, seasonID int) 

INSERT INTO @dateSeasons 
SELECT D.[date], S.ID 
FROM @dates AS D 
CROSS APPLY (

    SELECT TOP 1 ID 
    FROM dbo.Seasons 
    WHERE bookingID = @bookingID 
    AND D.[date] BETWEEN startDate AND endDate 
    ORDER BY ID DESC 

) AS S 


SELECT MIN([date]), endDate, DATEDIFF(DAY, MIN([date]), DATEADD(DAY, 1, endDate)), seasonID 
FROM (

    SELECT S1.seasonID, S1.[date], (

     SELECT MAX([date]) 
     FROM @dateSeasons S2 
     WHERE S2.seasonID = S1.seasonID 
     AND NOT EXISTS (

      SELECT NULL 
      FROM @dateSeasons S3 
      WHERE S3.[date] < S2.[date] 
      AND S3.[date] > S1.[date] 
      AND S3.seasonID <> S1.seasonID 

     ) 

    ) AS endDate 
    FROM @dateSeasons S1 
) AS results 
GROUP BY endDate, seasonID 
ORDER BY MIN([date]) 
+1

« Ce qu'il fait est pas important » - Je pense que vous allez est! Souvent, les gens vous diront leur solution perçue à un problème plutôt que le problème réel qu'ils tentent de résoudre. –

+0

Oui, c'est évidemment important pour moi, mais ce n'est pas important pour la question que je pose. – markvpc

+1

Ce qui est le mieux dépend fortement du SGBDR, des structures de table, des index et de la distribution de taille de vos données. Aucun d'entre eux n'est spécifié dans votre question. La meilleure façon de déterminer laquelle de deux requêtes est la meilleure est généralement de les tester les unes par rapport aux autres tout en observant les statistiques de requête et les plans de requête que votre SGBDR met à votre disposition. En ce qui concerne le commentaire de Mitch et votre réponse, il est généralement important parce que la réponse à ce qui est le mieux sera souvent «aucun de ce qui précède». –

Répondre

0

Vous cherchez plus propre est hors de propos par écrit le code SQL. Ce qui semble élégant est souvent le pire moyen possible de résoudre le problème du point de vue de la performance. La seule façon de savoir avec certitude ce qui est le mieux est de s'assurer d'abord que les deux méthodes que vous testez renvoient les mêmes résultats, puis les tester et vérifier les plans d'exécution (ou expliquer dans mySQL). Les techniques qui améliorent la requête sont également spécifiques à la base de données. Ce qui fonctionne le mieux pour optimiser les performances dans SQL Server peut être la pire des possibilités dans Oracle.

0

Parfois, vous pouvez obtenir de meilleures performances en utilisant un common table expression (CTE):

WITH 
dateSeasons ([date], [seasonID]) 
AS 
(
    SELECT D.[date], S.ID 
    FROM @dates AS D 
    CROSS APPLY (

     SELECT TOP 1 ID 
     FROM dbo.Seasons 
     WHERE bookingID = @bookingID 
     AND D.[date] BETWEEN startDate AND endDate 
     ORDER BY ID DESC 

    ) AS S 
) 

SELECT MIN([date]), endDate, DATEDIFF(DAY, MIN([date]), DATEADD(DAY, 1, endDate)), seasonID 
FROM (

    SELECT S1.seasonID, S1.[date], (

     SELECT MAX([date]) 
     FROM dateSeasons S2 
     WHERE S2.seasonID = S1.seasonID 
     AND NOT EXISTS (

      SELECT NULL 
      FROM dateSeasons S3 
      WHERE S3.[date] < S2.[date] 
      AND S3.[date] > S1.[date] 
      AND S3.seasonID <> S1.seasonID 

     ) 

    ) AS endDate 
    FROM dateSeasons S1 
) AS results 
GROUP BY endDate, seasonID 
ORDER BY MIN([date])