J'ai deux tables tabdata et tabdataDetaDetail.
Je veux toutes les iddata (pk) de la table parent (Tabdata) qui ont Toute autre combinaison n'est pas valide. Comment les obtenir? P>
Qu'est-ce que j'ai essayé sans succès (lent et me donne aussi des lignes qui ont uniquement fort> fiagctioncode 34): p>
Merci pour votre temps. P>
Edit2: Je pense que la réponse marquée est vraiment la solution la plus efficace et la plus compacte. P>
Edit3: La réponse de CoDesleuth est intéressante car elle ne renvoie que des lignes que d'avoir un seul code de fiagction = 11. Difficile de voir, parce que c'est seulement vrai pour 20 TabdataDetail-Rows OT de 41524189 Total-Rows qui en ont deux. Quoi qu'il en soit, cela n'était pas à 100% de ce que j'ai demandé ou plutôt de ce que je cherchais. P>
(source: BILDER-HOCHLADEN.net ) SUB> P>
6 Réponses :
Select ... From tabData As T1 Where Exists ( Select 1 From tabDataDetail As TDD1 Where TDD1.fiData = T1.idData And TDD1.fiactionCode = 11 ) And Not Exists ( Select 1 From tabDataDetail As TDD1 Where TDD1.fiData = T1.idData And TDD1.fiactionCode Not In(11,34) ) To expand on my logic, the first check (a correction) is to ensure that a row with fiActionCode = 11 exists. The second check works by first defining the set of rows we do not want. We do not want anything that is something other than fiActionCode = 11 or 34. Because that is the set of items we do not want, we search for anything that does not exist in that set.
Merci. Mais cela me donne aussi les rangées qui ne disposent que de 34 comme fiacction à la garde d'enfants. Ceux-ci devraient être exclus.
@Tim - corrigé. Il suffit de recevoir un contrôle supplémentaire pour vous assurer que la fiacctioncode = 11 existe.
PK est iddata et le nom de la table est Tabdata, mais mis à part de cela, il semble fonctionner (je ne sais pas pourquoi). Je reçois des rangées de 400k de sorte que c'est difficile à vérifier.
@Tim - Un simple vérification de vérification serait de déterminer si une ligne résultante a une ligne tabdataDetail avec une valeur de codes de fiagction égale à quelque chose d'autre que 34 (nous savons qu'il doit avoir une ligne avec une valeur = 11). Il suffit d'ajouter une jointure intérieure à TabdataDetail ferait une inspection visuelle plus facile.
@Thomas: super efficace, gentil!
@THOMAS: Pourriez-vous s'il vous plaît simplement changer "Sélectionnez ... à partir d'Iddata comme T1" pour "Select Iddata de Tabdata comme T1"? Cela pourrait être déroutant pour les autres. Merci.
EDIT: APOLS - Je vois ce que vous voulez dire avec des lignes d'enfants. Ce n'est pas particulièrement efficace. Merci également à Lieven pour les données.
SELECT idData FROM tabData td WHERE EXISTS ( SELECT 1 FROM tabDataDetail tdd WHERE tdd.fiData = td.idData AND fiActionCode = 11 ) AND NOT EXISTS ( SELECT 1 FROM tabDataDetail tdd WHERE tdd.fiData = td.idData AND fiActionCode <> 11 ) UNION SELECT idData FROM tabData td WHERE EXISTS ( SELECT 1 FROM tabDataDetail tdd WHERE tdd.fiData = td.idData AND fiActionCode = 11 ) AND EXISTS ( SELECT 1 FROM tabDataDetail tdd WHERE tdd.fiData = td.idData AND fiActionCode = 34 ) AND NOT EXISTS ( SELECT 1 FROM tabDataDetail tdd WHERE tdd.fiData = td.idData AND fiActionCode NOT IN (11, 34) )
raisonnement fort>
JOIN EXTÉRIEUR DE GAUCHE CODE> exclut tous les IDDATA qui ont une pièce d'identité différente de 11 ou 34 li>
avoir code> exclut tous les IDData que seul em> ont un 34 li>
SELECT *
FROM @tabData d
INNER JOIN @tabDataDetail dd ON dd.fiData = d.idData
INNER JOIN (
SELECT idData
FROM @tabData d
INNER JOIN @tabDataDetail dd ON dd.fiData = d.idData
LEFT OUTER JOIN (
SELECT fiData
FROM @tabDataDetail
WHERE fiActionCode NOT IN (11, 34)
) exclude ON exclude.fiData = d.idData
WHERE exclude.fiData IS NULL
GROUP BY
idData
HAVING MIN(fiActionCode) = 11
) include ON include.idData = d.idData
Merci, mais j'ai plusieurs 'l'identifiant multi-parties "d.iddata" ne pouvait pas être lié. " et "nom de colonne ambigu"
Avez-vous supprimé le @? La requête fonctionne sans problèmes sur mon système.
Travaille aussi (un peu lent). Merci
@Tim, une indexation correcte peut aller un long chemin à accélérer, mais ce sera difficile (sinon impossible) de battre Thomas ' ne pas exister code> solution.
édité ma réponse basée sur des éclaircissements donnés dans des commentaires sur d'autres réponses.
select td.idData from tabData td left join tabDataDetail tdd on td.idData = tdd.fiData and tdd.fiActionCode = 11 left join tabDataDetail tdd2 on td.idData = tdd2.fiData and tdd2.fiActionCode = 34 left join tabDataDetail tdd3 on td.idData = tdd3.fiData and tdd3.fiActionCode not in (11,34) where (tdd.fiData is not null or (tdd.fiData is not null and tdd2.fiData is not null)) and tdd3.fiData is null group by td.idData
merci @ Lieven pour le code de données pour tester ceci: requête: p> idData
-----------
1
2
(2 row(s) affected)
@Codesléuth, ne le mentionne pas. Le coût selon l'analyseur de performance est de 24% pour ma solution, 32% pour votre choix. Je suis intéressé à savoir dans un scénario du monde réel si cela tient.
Je n'ai pas vraiment examiné la question ou cette réponse dans un détail, mais comme un point général n'existe pas code> est plus efficace que
Count (*) code> dans SQL Server tel quel une jointure anti-semi. Il suffit de vérifier qu'une ligne correspondante n'existe pas. Ne comptez pas tous ceux qui correspondent.
@Lieven: Coût de quoi? Juste la sous-requête? Désolé, je semble avoir obtenu pas dans code> mélangé dans ma tête avec
n'existe pas code> - je me trompe, la performance est en réalité meilleure que le compte
code > dans ma réponse. Je vais le modifier. Bravo!
@Lieven, @Martin Smith: corrigé, désolé à ce sujet :(
La requête renvoie 212040 Tabdata lignes mais le résultat correct devrait être de 212050. Je ne sais pas encore pourquoi.
@Tim: Lesquels manquent-ils?
Intéressant. Les 10 rangées ont 2 lignes de détail chacune avec deux codes de fiacction = 11 (ce qui devrait être impossible dans mon BL). Je dois donc admettre que votre résultat est le plus précis.
Il ne s'agissait pas de la question à 100% à 100% à la recherche de fiagctioncode = 11 uniquement en termes de non-autres codes de fiacction ou uniquement en termes de célibataire. J'ai besoin d'une première alternative. Mais était intéressant de voir qu'il est possible d'avoir plus d'un 11. Merci.
@IM: Cool, j'avais supposé que vous aviez une contrainte en place pour cela, de ce qu'il semblait dans votre question. Je suis content que ma réponse vous ait aidé un peu plus loin :)
Cela le fait avec un passage à travers les données que je pense.
Cela dépend de la distribution des données, qu'il soit préférable de faire 2 recherches distinctes. P>
WITH matches AS ( SELECT fiData FROM tabDataDetail GROUP BY fiData HAVING COUNT(CASE WHEN fiactionCode = 11 THEN 1 END) > 0 AND COUNT(CASE WHEN fiactionCode NOT IN (11,34) THEN 1 END) = 0 ) SELECT ... FROM idData i JOIN matches m ON m.fiData = i.idData
Cela fonctionne aussi (lorsque vous changez 'Sélectionnez ... de IDData I' pour sélectionner IDData de Tabdata I '). Merci.
Il n'est jamais mentionné quelles colonnes sont nécessaires dans la sortie. N'est-ce que des colonnes Tabdata ou des données de TabdataDetail sont-elles requises?
Ce n'est que la clé primaire (IDDATA) qui m'intéresse et doit être regroupée (et ordonnée) par (si nécessaire). Mais pour vérifier le résultat, il est préférable d'avoir un code de fiagction également.