2010-12-13 6 views
0

Je suis perplexe sur une requête sql.Sql requête confusion

Dans une requête, j'ai un jeu de résultats comme ceci:

FooId  Name  Value  SourceLevel SourceId RecordId 
----------------------------------------------------------------- 
    1  'Foo'  10    1   0   1 
    1  'Foo'  25    3   1   2 
    2  'Bar'  33    1   0   3 

Pour cette requête, je passe des paramètres @ Level1Level, @ Level2Level, @ Level3Level et @ Level1Id, @ Level2Id, @ Level3Id

(non, ce ne sont pas de vrais noms, mais ils illustrent mon propos).

Ma requête essaie de faire un filtre comme ceci:

WHERE ((SourceLevel = @Level1Level AND SourceId = @Level1Id) 
OR (SourceLevel = @Level2Level AND SourceId = @Level2Id) 
OR (SourceLevel = @Level3Level AND SourceId = @Level3Id)) 

Si je passe des paramètres comme ceci:

@Level1Level = 1, @Level2Level = 2, @Level3Level = 3 
@Level1Id = 0, @Level2Id = 3, @Level3Id = 2 

Je veux recordIds 1 et 3 arrière.

Mais, si je passe des paramètres comme ceci:

@Level1Level = 1, @Level2Level = 2, @Level3Level = 3 
@Level1Id = 0, @Level2Id = 3, @Level3Id = 1 

Je veux recordIds 2 et 3 arrière. Malheureusement, dans le second cas, je récupère tous les trois enregistrements, ce qui est logique, à cause de la clause OR dans ma clause where. Je n'arrive pas à comprendre comment limiter mon jeu de résultats pour dire "seulement choisir SourceLevel 1 si je n'ai pas déjà fait de correspondance avec SourceLevel 2 ou 3".

Quelqu'un at-il des idées, en supposant que cela ait un sens?

Pour clarifier: Je veux que chacun fooid de mon jeu de résultats, mais seulement le fooid plus spécifique disponible, sur la base des paramètres de SourceLevel passé dans

+0

Les données de votre échantillon sont-elles correctes? Vous avez les mêmes valeurs pour 'SourceLevel' et 'SourceId' pour les première et troisième lignes. – Tony

+0

Oui, ils sont différents FooIds ... Je veux chaque FooId dans le résultat, mais seulement le plus spécifique basé sur le SourceLevel. – Jonas

+0

Je comprends mais les SourceLevel et SourceID pour RecordID 1 & 3 sont exactement les mêmes. Si vous utilisez SourceLevel et SourceID pour vous différencier, vous obtiendrez toujours les deux lignes. Voir aussi la réponse de Bugai13, il a tracé les combinaisons possibles. – Tony

Répondre

2

Voici ce que je fini par faire:

WHERE 
(
    (SourceLevel = @Level3Level AND SourceId = @Level3Id) 
    OR 
    (
    SourceLevel = @Level2Level AND SourceId = @Level2Id 
    AND NOT EXISTS (SELECT 'X' FROM SourceTable WHERE SourceLevel = @Level3Level And SourceId = @Level3Id AND FooId = SourceTable.FooId) 
) 
    OR 
    (
    SourceLevel = @Level1Level AND SourceId = @Level1Id 
    AND NOT EXISTS (SELECT 'X' FROM SourceTable WHERE SourceLevel = @Level3Level And SourceId = @Level3Id AND FooId = SourceTable.FooId) 
    AND NOT EXISTS (SELECT 'X' FROM SourceTable WHERE SourceLevel = @Level2Level And SourceId = @Level2Id AND FooId = SourceTable.FooId) 
) 
) 

Cela semble faire le filtrage que je cherchais ... désolé que la question était si confuse. :)

0
(SourceLevel = 1 AND SourceId = 0) match 1 and 3 records 
(SourceLevel = 2 AND SourceId = 3) no matches 
(SourceLevel = 3 AND SourceId = 1) match 2 record 

Les trois dossiers seront retournés par la requête..

0

Je ne vois pas exactement le point et pourquoi c'est une question sql. Mais si vous voulez SourceLevel 1 (je l'appelle maintenant SL1) que si vous n'êtes pas encore SL2 ou SL3 ...

pourquoi ne pas essayer avec ceci:

SL2 OU SL3 OU (PAS SL2 ET NON SL3 ET SL1)