2010-02-23 18 views
1

Compte tenu de ces tablesrequête T-SQL pour trouver manquants ID pour une plage de dates

table Channel 
-------------- 
ChannelID int IDENTITY 
<other irrelevant stuff> 

table Program 
-------------- 
ProgramID int IDENTITY 
ChannelID int 
AiringDate datetime 
<other irrelevant stuff> 

et cette requête

SELECT C.ChannelID, t.AiringDate 
FROM 
Channel C 
LEFT JOIN ( 
    SELECT distinct ChannelID 
    FROM Program 
    WHERE AiringDate = '2010-01-16' 
) p 
     ON p.ChannelID=C.ChannelID 
CROSS JOIN (
    SELECT AiringDate = '2010-01-16' 
) t 
WHERE C.ChannelID IN (1, 2, 74, 15, 906) /* the Channel table contains more channels than we are interested in */ 
    AND p.ChannelID IS NULL 

qui donne

ChannelID | AiringDate 
----------|----------- 
    2  | 2010-01-16 
    906 | 2010-01-16 

comment puis-je modifier pour accepter une plage de dates, de sorte que le résultat sera quelque chose comme

ChannelID | AiringDate 
----------|----------- 
    2  | 2010-01-16 
    906 | 2010-01-16 
    2  | 2010-01-17 
    906 | 2010-01-17 

s'il n'y avait pas de programmes diffusés sur ces 2 canaux l'un de ces deux jours

Ce ne renvoie aucune ligne

SELECT C.ChannelID, t.AiringDate 
FROM 
Channel C 
LEFT JOIN ( 
    SELECT distinct ChannelID, AiringDate 
    FROM Program 
    WHERE AiringDate between '2010-01-16' and '2010-01-17' 
) p 
     ON p.ChannelID=C.ChannelID 
CROSS JOIN (
    SELECT AiringDate = '2010-01-16' 
    union 
    SELECT AiringDate = '2010-01-17' 
) t 
WHERE C.ChannelID IN (1, 2, 74, 15, 906) 
    AND p.ChannelID IS NULL 

Ce CROSS JOIN est un peu laid, et il serait bien de se débarrasser de tout cela. Notez que le premier exemple de requête est un peu compliqué; Pour les dates simples que j'ai un simple qui ne sort que channelIds manquants:

SELECT C.ChannelID 
FROM 
Channel C 
LEFT JOIN ( 
    SELECT distinct ChannelID 
    FROM Program 
    WHERE AiringDate = '2010-01-16' 
) p 
     ON p.ChannelID=C.ChannelID 
WHERE C.ChannelID IN (1, 2, 74, 15, 906) 
    AND p.ChannelID IS NULL 

Répondre

2

Si je comprends correctement, cela devrait obtenir ce que vous avez demandé.

  • Combine tous les canaux avec tous les AiringDate
  • Sélectionnez tous les canaux ayant AiringDates entre les dates dont vous avez besoin.
  • LEFT JOIN pour supprimer tous les canaux ayant déjà AiringDates

Déclaration SQL

DECLARE @Channel TABLE (ChannelID INTEGER PRIMARY KEY) 
DECLARE @Program TABLE (ProgramID INTEGER PRIMARY KEY, ChannelID INTEGER, AiringDate DATETIME) 

INSERT INTO @Channel VALUES (1) -- Aired on 16 & 17 
INSERT INTO @Channel VALUES (2) -- Aired on 16 
INSERT INTO @Channel VALUES (3) -- Not Aired 

INSERT INTO @Program VALUES (1, 1, '01-16-2010') 
INSERT INTO @Program VALUES (2, 1, '01-17-2010') 
INSERT INTO @Program VALUES (3, 2, '01-16-2010') 


SELECT C.* 
FROM (
      SELECT C.ChannelID 
        , p.AiringDate 
      FROM @Channel C   
        CROSS JOIN ( 
        SELECT DISTINCT AiringDate 
        FROM @Program 
        WHERE AiringDate BETWEEN '01-16-2010' AND '01-17-2010' 
       ) p 
     ) c 
     LEFT OUTER JOIN (
      SELECT C.ChannelID, p.AiringDate 
      FROM @Channel C 
        INNER JOIN @Program p ON p.ChannelID = C.ChannelID 
      WHERE AiringDate BETWEEN '01-16-2010' AND '01-17-2010' 
     ) p ON p.ChannelID = C.ChannelID AND p.AiringDate = C.AiringDate 
WHERE p.ChannelID IS NULL AND p.AiringDate IS NULL 
+0

Hmm, à proximité! Cependant, cela ne fonctionne que s'il n'y avait pas de programme le 16 et il n'y avait pas de programme le 17. Mon exemple a peut-être manqué. Je veux trouver les chaînes qui n'ont diffusé aucun programme dans une certaine plage de dates, et aussi retourner les AiringDates qui auraient pu l'être. Donc une ligne par canal et par AiringDate. –

+0

En fait, en dehors de l'affreux select/union dont vous vous êtes débarrassé (ce qui est sympa!) Votre requête fait exactement la même chose que la seconde listée dans mon post original. Si je supprime mon O WH C.ChannelID IN (1, 2, 74, 15, 906) stipulation (que votre requête omis), j'obtiens les mêmes résultats. Les plans d'exécution sont identiques. –

+0

@ J F - J'ai ajouté quelques exemples de données. Pour ces données, qu'attendez-vous en tant que sortie? J'avais l'impression qu'il devrait retourner ChannelID 3 pour chaque date. –