2009-04-11 3 views
3

J'ai deux tables de base de données, les catégories et supercatégories, pour un système de contrôle d'inventaire Je travaille sur:requête SQL sur deux tables - lignes de retour dans une table qui ne sont pas entrées dans l'autre

Catégories: ID_Category, CategoryName

sUPERCATÉGORIES: ID_SuperCategory, CategoryID, SuperCategoryID

Je suis en train de relations catégorie-sous-catégorie dans la table supercatégories. Je mets toutes les catégories dans la table Catégories.

est un exemple:

 
    Categories: 
    ID_Category CategoryName 
    1   Box 
    2   Red Box 
    3   Blue Box 
    4   Blue Plastic Box 
    5   Can 
    6   Tin Can 
  
    SuperCategories: 
    ID_Super CategoryID SuperCategoryID 
    1  2   1 
    2  3   1 
    3  4   3 
    4  6   5 

et CategoryID SuperCategoryID renvoient à la ID_Category clé primaire dans la table Catégories.

Ce que je voudrais est une requête qui renvoie tous les noms des catégories qui ne sont pas les parents de toutes les autres catégories:

Red Box
Boîte en plastique bleu
Tin Can

Cela revient à trouver toutes les valeurs de ID_Category qui n'apparaissent pas dans la colonne SuperCategoryID (2, 4 et 6), mais j'ai du mal à écrire le SQL. Je utilise VB6 pour interroger une base de données Access 2000.

Toute aide est appréciée. Merci!

EDIT: J'ai répondu à la réponse de tout le monde qui m'a donné quelque chose qui a fonctionné. J'ai accepté la réponse que j'ai trouvée la plus instructive. Merci encore pour votre aide!

Répondre

6

La réponse de Mike Pone fonctionne, car il rejoint la table "Catégories" avec la table "SuperCategories" comme "LEFT OUTER JOIN" - cela prendra toutes les entrées de "Catégories" et ajoutera des colonnes de "SuperCategories" à celles où le lien existe - où il n'existe pas (par exemple s'il n'y a pas d'entrée dans "SuperCategories"), vous obtiendrez des valeurs NULL pour les colonnes SuperCategories - et c'est exactement ce que la requête de Mike vérifie ensuite.

Si vous écririez la requête comme ceci:

SELECT c.CategoryName, s.ID_Super 
FROM Categories c 
LEFT OUTER JOIN SuperCategories s ON c.ID_Category = s.SuperCategoryID 

vous obtiendrez quelque chose comme ceci:

CategoryName ID_Super 
Box    1 
Box    2 
Red Box   NULL 
Blue Box   3 
Blue Plastic Box NULL 
Can    4 
Tin Can   NULL 

Cela vous donne essentiellement votre réponse - toutes les lignes où la ID_Super sur la NULLE GAUCHE OUVERT est NULL sont ceux qui n'ont aucune entrée dans la table SuperCategories. Tout est clair? :-)

Marc

+0

Oui, cela efface. Je vous remercie! – John

2

Je ne sais pas si la syntaxe fonctionnera pour Access, mais quelque chose comme ça fonctionnerait:

select CategoryName from Categories 
where ID_Category not in (
    select SuperCategoryID 
    from SuperCategories 
) 
+0

Ce travaillerait dans Access AFAIK. –

+0

trop inefficace pour utiliser une sous-requête. Aller directement avec une jointure externe pour plus d'efficacité –

+0

Merci. Cela marche! – John

5

comprennent uniquement les catégories qui ne sont pas des super-cateogories. Un extérieur simple, rejoindre

select CategoryName from Categories LEFT OUTER JOIN 
SuperCategories ON Categories.ID_Category =SuperCategories.SuperCategoryID 
WHERE SuperCategories.SuperCategoryID is null 
+0

Merci! Cela marche. Maintenant, je dois juste comprendre pourquoi! – John

+0

Les jointures externes prendront tout du côté gauche de la jointure (c'est-à-dire tout de Catégories) et seulement les enregistrements qui correspondent à la table SuperCategories. –

6
SELECT 
    CAT.ID_Category, 
    CAT.CategoryName 
FROM 
    Categories CAT 
WHERE 
    NOT EXISTS 
    (
      SELECT 
       * 
      FROM 
       SuperCategories SC 
      WHERE 
       SC.SuperCategoryID = CAT.ID_Category 
    ) 

Ou

SELECT 
    CAT.ID_Category, 
    CAT.CategoryName 
FROM 
    Categories CAT 
LEFT OUTER JOIN SuperCategories SC ON 
    SC.SuperCategoryID = CAT.ID_Category 
WHERE 
    SC.ID_Super IS NULL 

Je vais aussi faire la suggestion que vos normes de nommage pourraient probablement utiliser un peu de travail. Ils semblent partout et difficile de travailler avec.

+0

Merci! C'est ma première expérience en SQL, donc j'ai beaucoup à apprendre. Je voulais dire ID_ pour la clé primaire et BlahBlahID pour indiquer qu'il s'agissait d'une clé dans une autre table. Toujours ouvert aux suggestions ... – John

+0

Merci. Cela fonctionne aussi bien! – John

1

Je prends toujours l'approche jointure externe comme marc_s suggère. Il y a beaucoup de puissance en utilisant OUTER JOINS. Souvent, je vais devoir faire une FULL OUTER JOIN pour vérifier les données des deux côtés de la requête.

Vous devriez également regarder la fonction ISNULL, si vous faites une requête où les données peuvent être dans la table A ou la table B puis j'utiliser la fonction ISNULL pour renvoyer une valeur de chaque colonne.

Voici un exemple


SELECT 
     isNull(a.[date_time],b.[date_time]) as [Time Stamp] 
     ,isnull(a.[ip],b[ip]) as [Device Address] 
     ,isnull(a.[total_messages],0) as [Local Messages] 
     ,isnull(b.[total_messages],0) as [Remote Messages] 
    FROM [Local_FW_Logs] a 
FULL OUTER JOIN [Remote_FW_Logs] b 
on b.ip = a.ip 
-1

J'ai deux tables interface_category et interface_subcategory.

Interface_subcategory contient SubcategoryID, CategoryID, Name(SubcategoryName)

Interface_category contient CategoryID, Name(CategoryName)

Maintenant, je veux sortie CategoryID et Nom (nom Sous-catégorie)

Interrogation I écrit est ci-dessous et son travail pour moi

select ic.CategoryID, ic.Name CategoryName, ISC.SubCategoryID, ISC.Name SubCategoryName from Interface_Category IC 
inner join Interface_SubCategory ISC 
on ISC.CategoryID = ic.CategoryID 
order by ic.CategoryID, isc.SubCategoryID 
Questions connexes