2009-01-28 6 views
0

J'ai 2 tables qui ont une relation many to many; Un individu peut appartenir à plusieurs groupes. Un groupe peut avoir plusieurs individus.Opérateur SQL logique AND pour les zones de bits

Les personnes essentiellement viennent leur ID de clé primaire

groupes ont un ID de clé primaire, IndividualID (identique à l'ID dans le tableau individuel), et un indicateur de bits pour si ce groupe est le groupe principal pour l'individu

En théorie, toutes les entrées d'un individu donné dans la table de groupe, à l'exception d'une seule, doivent être mises à false, car chaque individu doit avoir exactement 1 groupe principal.

Je sais que pour mon ensemble de données actuel, cette hypothèse n'est pas vraie, et j'ai des individus qui ont le drapeau primaire pour TOUS leurs groupes mis à faux.

Je n'arrive pas à générer une requête qui me renverra ces individus.

Le plus proche que j'ai obtenu est:

SELECT * FROM individuel i Groupe LEFT JOIN g SUR g.IndividualID = i.ID OÙ g.IsPrimaryGroup = 0

mais aller plus loin avec SUM ou MAX ne fonctionne pas, car le champ est un champ de bits, et non un numérique.

Des suggestions?

Répondre

0

Vous devez inclure la condition IsPrimaryGroup dans la clause JOIN. Cette requête trouve tous les individus sans jeu de PrimaryGroup:

SELECT * FROM Individual i 
LEFT OUTER JOIN Group g ON g.IndividualID = i.ID AND g.IsPrimaryGroup = 1 
WHERE g.ID IS NULL 

Cependant, le moyen idéal pour résoudre votre problème (en termes de db relationnelle) est d'avoir un PrimaryGroupID dans le tableau individuel.

1

Je ne sais pas vos données ... mais .... que LEFT JOIN est un INNER JOIN

ce qui se passe lorsque vous modifiez la OÙ ET

SELECT * FROM Individual i 
LEFT JOIN Group g ON g.IndividualID = i.ID 
AND g.IsPrimaryGroup = 0 

ici essayez d'exécuter ce. ... non testé bien sûr puisque vous ne l'avez pas fourni de données suffisantes

SELECT SUM(convert(int,g.IsPrimaryGroup)), i.ID 
FROM Individual i 
LEFT JOIN [Group] g ON g.IndividualID = i.ID 
AND g.IsPrimaryGroup = 0 
GROUP BY i.ID 
HAVING COUNT(*) > 1 
1

Essayez de ne pas utiliser un champ de bits si vous devez faire SUM et MAX - utiliser un TINYINT à la place. De plus, d'après ce dont je me souviens, les champs de bits ne peuvent pas être indexés, donc vous perdrez des performances dans vos jointures.

1

Mise à jour: Je l'ai fait fonctionner avec un sous-ensemble. Sélectionnez IndividualID du groupe où le groupe primaire est faux, et individualID NOT IN (sélectionnez IndividualID du groupe où le groupe primaire est vrai)

+0

Juste un FYI, si votre base de données prend en charge la clause EXISTS, elle est généralement plus rapide grâce à une meilleure utilisation des index. Voir mon message ci-dessous. – Dylan

0
SELECT COUNT(bitflag),individualId 
FROM Groups 
WHERE bitflag = 1 
GROUP BY individualId 
ORDER BY SUM(bitFlag) 
HAVING COUNT(bitFlag) <> 1 

Cela vous donnera chacun et combien de groupes primaires, ils ont

0

Je ne sais pas si cela est optimal du point de vue des performances, mais je crois que quelque chose dans ce sens devrait fonctionner. J'utilise OrgIndividual comme nom de la table de résolution entre le Individuel et le Groupe.

SÉLECTIONNER DISTINCT (i.IndividualID)
DE
    individuel i INNER JOIN OrgIndividual Oi
        SUR i.IndividualID = oi.IndividualID ET oi.PrimaryOrg = 0
    LEFT JOIN OrgIndividual PSO
        ON oi.IndividualID = oip.IndividualID ET oi.PrimaryOrg = 1
O WH
    oi2.IndividualID I SUN

0
SELECT IndividualID 
FROM Group g 
WHERE NOT EXISTS (
    SELECT NULL FROM Group 
    WHERE PrimaryOrg = 1 
    AND IndividualID = g.IndividualID) 
GROUP BY IndividualID 
Questions connexes