2011-11-03 4 views
2

Je le tableau suivant:Rejoindre à la même table dans SQL - SQL Server 2008

ID Type Description IDOfSystem 
-------------------------------- 
1000 Company Company Item NULL 
1010 System System Item NULL 
1020 Company NULL   1010 

J'ai éléments du système et la société. J'ai besoin d'écrire une requête select qui obtient tous les éléments de la société et les éléments du système SAUF si un élément de la société a une valeur dans IDOfSystem Je dois exclure cet élément du système et obtenir la description de l'élément du système. Donc, compte tenu du tableau ci-dessus, la sélection SQL doit renvoyer les lignes 1000, 1020 (avec "System Item") comme description.

Si 1020 ne trouvait pas, je voudrais simplement obtenir 1000 et 1010.

Je suppose que je peux briser cette place en plusieurs requêtes et faire un UNION. J'ai essayé de faire une jointure externe gauche sur la même table mais n'ai pas pu obtenir la description de la rangée de système.

Une aide?

Répondre

0

Cette approche utilise une auto-jointure pour rechercher la description du système correspondant. Une sous-requête séparée filtre les systèmes référencés.

select yt1.Id 
,  yt1.Type 
,  coalesce(yt2.Description, yt1.Description) as Description 
from YourTable yt1 
left join 
     YourTable yt2 
on  yt1.type = 'Company' 
     and yt2.type = 'System' 
     and yt2.ID = yt1.IDOfSystem 
where yt1.type in ('System', 'Company') 
     and not exists 
     (
     select * 
     from YourTable yt3 
     where yt1.type = 'System' 
       and yt3.type = 'Company' 
       and yt1.ID = yt3.IDOfSystem 
     ) 

Working example at SE Data.

+0

Il voulait également remplacer la description des lignes avec un système référencé avec la description du système (pas l'entreprise) –

+0

@Dylan Smith: Vous avez raison, je vais éditer la réponse, merci – Andomar

+0

Cela ne donne pas moi la description de l'élément du système. C'est une chaîne vide :( – Nick

1
SELECT 
    Companies.ID 
    ,Companies.Type 
    ,COALESCE(Systems.Description, Companies.Description) as Description 
FROM YourTable Companies 
LEFT OUTER JOIN YourTable Systems on Systems.ID = Companies.IDOfSystem 
WHERE NOT EXISTS 
(
    SELECT * FROM YourTable T3 WHERE T3.IDOfSystem = Companies.ID 
) 

Here il fonctionne sur SEDE.

+0

Cela ne fonctionne pas comme je ne comprends pas la description du système – Nick

+0

Vous pouvez consulter un exemple de travail de ce [ ici] (http://data.stackexchange.com/stackoverflow/q/116529/). Merci à @Andomar pour m'avoir éclairé sur l'utilité de SEDE. – kevev22

1
SELECT ID, Type, Description 
FROM MyTable AS A 
WHERE IDOfSystem IS NULL AND NOT EXISTS (SELECT * 
             FROM MyTable AS B 
             WHERE B.IDOfSystem = A.ID) 
UNION ALL 
SELECT A.ID, A.Type, B.Description 
FROM MyTable AS A INNER JOIN MyTable AS B ON A.IDOfSystem = B.ID 
WHERE IDOfSystem IS NOT NULL 

Ce que je fais est d'abord sélectionner toutes les lignes qui ne disposent pas d'un système référencé, et ne sont pas utilisés comme un autre système de lignes.

Ensuite, je fais une union avec une autre requête qui trouve toutes les lignes avec un système référencé, et de rejoindre le système pour saisir sa description.

+0

Je voudrais éviter une 'union' si possible car la vraie requête est assez énorme et je déteste la dupliquer. – Nick

+0

ouais, j'ai essayé de penser à un moyen de le faire sans UNION, et je ne pouvais pas trouver un moyen facile. Si personne d'autre ne se présente avec une façon non syndicale de le faire, je peux probablement écrire quelque chose plus tard. –

0

Je suis sûr qu'il ya de meilleures façons de le faire, mais essayez:

SELECT A.Id, A.Type, ISNULL(A.Description,B.Description) Description, A.IDOfsystem 
FROM YourTable A 
LEFT JOIN YourTable B 
ON A.IDOFSystem = B.ID 
WHERE A.ID NOT IN (SELECT IDOfsystem FROM YourTable WHERE IDOfsystem IS NOT NULL)