2008-12-13 8 views
2

J'ai une base de données (NexusDB (supposément compatible SQL-92)) qui contient une table Item, une table Category et une table ItemCategory plusieurs-à-plusieurs, qui est juste une paire de clés. Comme vous pouvez vous y attendre, les éléments sont affectés à plusieurs catégories.Question SQL: exclusion des enregistrements

Je suis désireux de tout l'utilisateur final de sélectionner tous les éléments qui sont

ItemID | ID catégorie
--------------------------------
01 | 01
01 | 02
01 | 12

02 | 01
02 | 02
02 | 47

03 | 01
03 | 02
03 | 14
etc ...

Je veux être en mesure de sélectionner tous les années Itemid qui sont affectés à des groupes X, Y et Z, mais pas affectés à des groupes P et Q.

Pour l'exemple données ci-dessus Par exemple, disons que je voudrais attraper tous les objets assignés aux catégories 01 ou 02 mais PAS 12 (rapportant les articles 02 et 03). Quelque chose le long des lignes de:

SELECT ItemID OÙ (CategoryID IN (01, 02))

... et supprimer de ce jeu SELECT ItemID OU PAS (CategoryID = 12)

Ceci est probablement une question SQL assez basique, mais ça me bouscule pour le moment. Toute aide w/b apprécié.

+0

Merci à tous! La réponse de Tom était parfaite pour ce dont j'avais besoin, mais tout était instructif pour moi. Beaucoup à apprendre sur SQL encore (je suis sûr que je serai de retour w/plus de questions) ... Merci pour l'aide. :) – Jamo

Répondre

2

Vous pouvez essayer avec SAUF

SELECT ItemID FROM Table 
EXCEPT 
SELECT ItemID FROM Table 
WHERE 
CategoryID <> 12 
1
SELECT i.ItemID, ic.CategoryID FROM Item AS i 
INNER JOIN ItemCategory ic 
ON i.ItemID = ic.ItemID 
WHERE ic.CategoryId = 1 OR ic.CategoryId = 2 

Bien sûr, vous avez besoin de mettre dans la clause WHERE ce que les catégories que vous voulez obtenir.

+0

Ceci obtiendra des articles dans la catégorie 1 même s'ils ne sont pas dans la catégorie 2. Je ne pense pas que c'est ce que l'affiche originale veut. –

0

Pour le cas simple que vous avez avec un faible nombre et connu des catégories que vous pouvez simplement utiliser plusieurs jointures pour vérifier l'existence et la non-existence:

SELECT 
    ItemID 
FROM 
    Items I 
INNER JOIN ItemCategories IC1 ON IC1.ItemID = I.ItemID AND IC1.CategoryID = '01' 
INNER JOIN ItemCategories IC2 ON IC2.ItemID = I.ItemID AND IC2.CategoryID = '02' 
LEFT OUTER JOIN ItemCategories IC3 ON IC3.ItemID = I.ItemID AND IC3.CategoryID = '12' 
WHERE IC3.ItemID IS NULL 

Pour un cas plus général, étant donné un inconnu nombre d'éléments dans la correspondance et ne correspondent pas aux listes, vous pouvez utiliser la requête suivante. J'ai utilisé une variable de table (disponible dans SQL Server) pour chacune des listes, mais vous pouvez utiliser une sélection par rapport à une table réelle ou une liste de variables/paramètres si nécessaire. L'idée reste la même:

SELECT 
    ItemID 
FROM 
    Items I 
WHERE 
    (
     SELECT COUNT(*) 
     FROM ItemCategories IC1 
     WHERE IC1.ItemID = I.ItemID 
     AND IC.CategoryID IN 
      (SELECT CategoryID FROM @MustHaves) 
    ) = (SELECT COUNT(*) FROM @MustHaves) AND 
     (
     SELECT COUNT(*) 
     FROM ItemCategories IC1 
     WHERE IC1.ItemID = I.ItemID 
     AND IC.CategoryID IN 
      (SELECT COUNT(*) FROM @MustNotHaves) 
    ) = 0 
2

Je veux être en mesure de sélectionner tous ceux qui sont de de Itemid affectés à Catégories X, Y et Z, mais pas attribués aux catégories P et Q.

Je ne peux pas confirmer à partir de la documentation de NexusDB sur SELECT qu'ils prennent en charge les sous-requêtes, mais ils prennent en charge LEFT OUTER JOIN et GROUP BY.Donc, voici une requête qui fonctionne dans ces restrictions:

SELECT i1.ItemID 
FROM ItemCategory i1 
    LEFT OUTER JOIN ItemCategory i2 
    ON (i1.ItemID = i2.ItemID AND i2.CategoryID IN ('P', 'Q')) 
WHERE i1.CategoryID IN ('X', 'Y', 'Z') 
    AND i2.ItemID IS NULL 
GROUP BY i1.ItemID 
HAVING COUNT(i1.CategoryID) = 3; 
+0

Belle méthode +1 :) –