Un moyen plus efficace d'interroger ces données?

J'ai une table avec des données:

  ColA |  ColB |  ColC
 ------ + ------ + ------
   1 |  A |  X
   2 |  A |  Y
   3 |  B |  Y
   4 |  C |  Y
   5 |  C |  Z
   6 |  D |  Y
   7 |  D |  Z

Je veux interroger pour get toutes les lignes où ColB et ColC tant que paire correspondent à une condition:

 SELECT * FROM [Table] WHERE (ColB = A AND ColC = Y) OR (ColB = B AND ColC = Y) OR (ColB = C AND ColC = Y) OR (ColB = D AND ColC = Z) 

cela devrait returnner les lignes 2, 3, 4 et 7.


Les paires de valeurs pour (ColB, ColC) pourraient potentiellement être grandes (dans la région de ~ 100). Existe-t-il un moyen plus efficace d'interroger ces données autres qu'une grande requête avec beaucoup de conditions OR ?

J'espère qu'il y a une façon d'utiliser un équivalent de Tuple, ce qui signifie que je peux faire quelque chose comme:

 SELECT * FROM [Table] WHERE (ColB, ColC) IN ({A, Y}, {B, Y}, {C, Y}, {D, Z}) 

Des idées?


EDIT: (pour répondre à quelques questions dans les commentaires)

Les champs pour ColB et ColC stockent des guids et sont déclarés en tant uniqueidentifier types uniqueidentifier .
Cela doit fonctionner sur SQL Server 2005 vers le haut (toutes les éditions).
La table a de l'ordre de millions de lignes, et je ne suis pas opposé à l'ajout d'indices qui sont nécessaires pour que cela fonctionne.

Tu pourrais le faire. (Si vous êtes sur SQL Server 2008, vous pouvez utiliser les constructors de lignes de values plutôt que union alls )

Vous devez vérifier le plan de requête pour voir s'il est plus efficace.

 SELECT * /*But don't use star*/ FROM [Table] JOIN ( SELECT 'A' AS BMatch, 'Y' AS CMatch UNION ALL SELECT 'B' AS BMatch, 'Y' AS CMatch UNION ALL SELECT 'C' AS BMatch, 'Y' AS CMatch UNION ALL SELECT 'D' AS BMatch, 'Z' AS CMatch UNION ALL ... ) Matches ON ColB = BMatch AND ColC = CMatch 

Vous dites dans les commentaires que la combinaison de ColB et ColC est unique donc (en supposant que votre table a déjà un index clusterisé) j'imagine si vous créez un unique nonclustered index non unique nonclustered index sur (colb, colc) ou (colc, colb) que le ci-dessus devrait vous donner un plan avec 100 searchs d'index suivies de 100 searchs de signets. Si ce n'est pas le cas, vous pouvez essayer d'append un indice pour l'utiliser pour utiliser le nouvel index. Vous auriez besoin de comparer les E / S pour cela avec les E / S d'une parsing complète, car beaucoup de or vous donnerait probablement.

Le coût des searchs de signets pourrait potentiellement être évité en incluant les colonnes supplémentaires requirejses dans l'index non groupé. Vous avez utilisé * mais je ne sais pas si cela serait viable. Vous devez équilibrer les avantages de cette requête par rapport aux avantages possibles pour les opérations de modification de données.

Avez-vous envisagé d'append une colonne calculée en tant que concaténation des deux colonnes?

Cela simplifierait votre instruction select et permettrait d'append un index.

 CREATE TABLE [dbo].[Table] ( ColA INTEGER , ColB VARCHAR(1) , ColC VARCHAR(1) , ColBC AS ColB + ColC ) CREATE UNIQUE INDEX IX_TABLE_COLBC ON [dbo].[Table] (ColBC) INSERT INTO [Table] VALUES(1, 'A', 'X') INSERT INTO [Table] VALUES(2, 'A', 'Y') INSERT INTO [Table] VALUES(3, 'B', 'Y') INSERT INTO [Table] VALUES(4, 'C', 'Y') INSERT INTO [Table] VALUES(5, 'C', 'Z') INSERT INTO [Table] VALUES(6, 'D', 'Y') INSERT INTO [Table] VALUES(7, 'D', 'Z') 

Pas exactement l'équivalent d'un Tuple, mais cela vous permet de changer votre sélection pour

 SELECT * FROM [Table] WHERE (ColBC) IN ('AY', 'BY', 'CY', 'DZ') 

et il utilise l'index.

Pourquoi ne pas créer une nouvelle table pour filterr votre jeu de résultats? Avec environ 100 valeurs à filterr, cette solution serait plus flexible si vos conditions de filter changeaient dans le futur, c'est-à-dire que vous changiez simplement la table de filtrage plutôt que de changer la clause "where" qui serait incluse dans votre instruction select:

si existe (select * à partir de sys.objects WHERE object_id = object_id (N'dbo.Filter ') ET saisissez (N'U'))
drop table dbo.Filter

créer une table dbo.Filter (
ColB char (1) non nul,
ColC char (1) non nul,
contrainte key primaire pkFilter en cluster (ColB, ColC) avec fillfactor = 100)

insert dans les valeurs dbo.Filter (ColB, ColC) ('A', 'Y'), ('B', 'Y'), ('C', 'Y'), ('D', 'Z')

select * dans [Table] comme t
jointure interne dbo.Filter comme f sur t.ColB = f.ColB et t.ColC = f.ColC