2013-03-15 5 views
0

J'ai une table que j'ai besoin de rejoindre avec elle-même et trouver les éléments manquants et je suis coincé. Peut-être que c'est juste un problème d'inexpérience, mais il me semble que je ne peux penser qu'en termes de boucle pour accomplir ce que je veux.Éviter une boucle for dans SQL

essentiellement la table est la suivante:

packageID  Server 
     1   baseline 
     2   baseline 
     3   baseline 
     1   server1 
     3   server1 
     2   server2 
     3   server2 

Ce que j'espère accomplir est de trouver ce que les paquets sont absents de chaque serveur. Je peux obtenir ceci sur un serveur par chaque serveur comme ceci:

SELECT base.*, ISNULL(dp.server,'server1') as Server 
    FROM (SELECT DISTINCT packageID FROM DB1 
      WHERE server = 'baseline') base 
    LEFT OUTER JOIN 
     (SELECT packageID, server FROM DB1 
      WHERE server = 'server1') dp 
    WHERE dp.server IS NULL 

Ce qui me donne ce que je veux sur une base de serveur individuel. Comment pourrais-je accomplir obtenir une liste de chaque paquet d'un serveur particulier est manquant de la ligne de base?

+0

Comment connaître le nombre de serveurs? Vous n'avez pas besoin d'une table de serveurs? – pedromarce

+0

Je pourrais obtenir une liste de serveurs dans une vue en obtenant un serveur distinct de cette liste si cela aiderait dans une solution? – Giled

+0

Mon point est, et si un serveur n'a pas de paquets déployés? Ensuite, il n'apparaîtra pas du tout, ni dans la table ni dans la vue, mais vous aurez toujours besoin de savoir qu'ils sont manquants. – pedromarce

Répondre

1

En supposant une vue avec la liste des SERVEURS, et le prendre comme pseudo-SQL que je ne peux pas tester, quelque chose comme ça devrait fonctionner, je pense ...

SELECT base.packageID, servers.server, 
      (SELECT count(*) 
       FROM base AS b1 
       WHERE b1.packageId = base.packageId 
       AND b1.server = servers.server) deployed 
    FROM base, servers 
WHERE base.server = 'baseline' 
    AND deployed = 0; 
+0

Merci beaucoup pour la réponse! Si cela ne vous dérange pas, pourriez-vous expliquer la pièce déployée un peu, je ne suis pas sûr de comprendre – Giled

+0

Bien sûr, il vérifie que chaque paquet de base vérifie chaque serveur et compte le nombre d'occurrences dans la table de base (qui sera toujours 0 ou 1), s'il n'y a pas d'occurrence (0 dans déployé) alors vous savez – pedromarce

+0

Merci encore, je me sentais sale en faisant une boucle en PowerShell – Giled

0

Essayez ce script,

 DECLARE @DB1 TABLE 
(
    PackageID INT 
    ,Server VARCHAR(50) 
) 


INSERT INTO @DB1 VALUES(1,'baseline') 
INSERT INTO @DB1 VALUES(2,'baseline') 
INSERT INTO @DB1 VALUES(3,'baseline') 
INSERT INTO @DB1 VALUES(1,'server1') 
INSERT INTO @DB1 VALUES(3,'server1') 
INSERT INTO @DB1 VALUES(2,'server2') 
INSERT INTO @DB1 VALUES(3,'server2') 

;WITH CTE_Package AS 
(
    SELECT DISTINCT PackageID 
     , ROW_NUMBER() OVER(order by PackageID) AS ID 
    FROM @DB1 
) 
,CTE_Servers AS 
(
    SELECT DISTINCT Server 
     , ROW_NUMBER() OVER(order by PackageID) AS ID 
    FROM @DB1 
) 
,CTE_Server_Packages AS 
(
    SELECT DISTINCT P.PackageId, S.Server 
    FROM CTE_Servers S 
    CROSS JOIN CTE_Package P  
) 
SELECT Server, PackageID 
FROM 
(
    SELECT SP.Server, SP.PackageID , D.PackageID [ActualPackage], D.Server [ActualServer] 
    FROM CTE_Server_Packages SP 
    LEFT JOIN @DB1 D 
      ON D.PackageID = SP.PackageID 
      AND D.Server = SP.Server 
) AS TEMP 
WHERE TEMP.ActualServer IS NULL