2010-12-12 6 views
2

Disons que nous avons une procédure stockée qui utilise un paramètre qui est @IsAllowed valeur booléenne et dans le cas où il est passé True je sélectionner des données de deux tables A,B (je vais utiliser dans mon cas Union ALL) Sinon il est passé False je sélectionner les données d'un Table A ... Je l'écris, il int comme suit:Comment choisir Union ALL en fonction du paramètre transmis (besoin d'optimisation)?

Create PROCEDURE TestSP 
(
    @IsAllowed bit 
) 
AS 

IF @IsAllowed = 1 
BEGIN 
    Select ID, Username From A 
    Union ALL 
    Select ID, Username From B 
END 
ELSE 
    Select ID, Username From A 

Est-ce la meilleure façon de le faire? bien que dans mon cas réel SP ai environ 9 paramètre utilisé dans où condition de première requête, cela signifie que je vais écrire la première requête deux fois et tout changement je dois prendre soin d'avoir la même copie dans les 2 différents endroits

+0

Est-ce que 'B' est un sous-ensemble de' A'? Ou deux ensembles de résultats distincts d'une seule table? – Brad

+0

Quelle version de SQL? – Brad

+0

A est un tableau qui diffère de la structure de la table B, mais il a des colonnes que je veux retourner ... j'utilise sql server 2005 –

Répondre

0

Essayez-le.

SELECT * 
FROM A 
UNION ALL 
SELECT * 
FROM B 
WHERE @isAllowed = 1 
+0

est-ce que cela affectera les performances car il va itérer toutes les lignes dans la table B.? –

+0

Laissez-moi faire une vérification rapide. Je vais jeter un coup d'oeil au plan d'exécution. – Brad

+0

Il semble effectuer un scan d'index en cluster sur la deuxième table de la requête. Il compte (dans mes tests simples) pour environ 45-50% du coût d'exécution. Je voudrais l'essayer dans votre scénario spécifique et voir si elle est dans les paramètres nécessaires. Toutes mes questions sont revenues en moins d'une seconde ou deux même lorsque je renvoyais des milliers de disques. – Brad

0

Je ne suis pas fou de cette requête, mais si vous voulez éviter complètement le coût de la sélection secondaire, je pense que vous devrez échanger hors d'une table temporaire.

IF OBJECT_ID('tempdb..#tableA') IS NOT NULL 
    DROP TABLE #tableA 

SELECT ID,Username 
INTO #tableA 
FROM tableA 

IF @isAllowed = 1 
    BEGIN 
     SELECT ID,Username 
     FROM #tableA 
     UNION ALL 
     SELECT ID,Username 
     FROM B 
    END 
ELSE 
    BEGIN 
     SELECT ID,Username 
     FROM #tableA 
    END 

DROP TABLE #tableA 

Sentez-vous libre de changer la table # à une table @ si votre jeu d'enregistrements est assez petit pour que ça ne vous dérange pas de mettre en mémoire (par opposition à écrire sur le disque - E/S est un des principaux goulots d'étranglement). Gardez juste à l'esprit que vous devrez déclarer la table (avec les définitions de colonnes) par opposition à SELECT ing INTO.

Questions connexes