Existe-t-il une meilleure option que Union Tout pour plusieurs sélections de la même ligne?

10

Exemple de schéma:

CREATE TABLE [dbo].[Base](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Option1ID] [int] NULL,
[Option2ID] [int] NULL,
[Option3ID] [int] NULL,
[Option1Name] [varchar] NULL,
[Option2Name] [varchar] NULL,
[Option3Name] [varchar] NULL,
[Option1LName] [varchar] NULL,
[Option2LName] [varchar] NULL,
[Option3LName] [varchar] NULL,)

Existe-t-il un moyen d'obtenir des résultats qui apparaissent comme:

ID | OptionID | OptionName | OptionLName

J'ai essayé d'y parvenir en utilisant UNION ALL, mais cela signifie que je dois parcourir la même ligne 3 fois dans mon exemple, dans mon vrai problème, je dois le faire 10 fois. Je ne peux pas normaliser la table en raison du code hérité. Existe-t-il un moyen de ne parcourir la ligne de base qu'une seule fois?

JustinDoesWork
la source

Réponses:

23

Vous pouvez utiliser CROSS APPLY ... VALUESpour UNPIVOTplusieurs colonnes

SELECT ID,
       OptionID,
       OptionName,
       OptionLName
FROM   [dbo].[Base]
       CROSS APPLY (VALUES([Option1ID], [Option1Name], [Option1LName]),
                          ([Option2ID], [Option2Name], [Option2LName]),
                          ([Option3ID], [Option3Name], [Option3LName])) 
                     V( OptionID, OptionName, OptionLName) 

Le plan d'exécution pour cela a un scan de Base. Le plan est en fait le même que pour la réécriture compatible 2005 qui utiliseUNION ALL

SELECT ID,
       OptionID,
       OptionName,
       OptionLName
FROM   [dbo].[Base]
       CROSS APPLY (SELECT [Option1ID], [Option1Name], [Option1LName] UNION ALL
                    SELECT [Option2ID], [Option2Name], [Option2LName] UNION ALL
                    SELECT [Option3ID], [Option3Name], [Option3LName]) 
                     V( OptionID, OptionName, OptionLName)  

Mais je suppose que ce que UNION ALLvous tentiez d'éviter était les multiples scans de

SELECT ID,
       [Option1ID],
       [Option1Name],
       [Option1LName]
FROM   [dbo].[Base]
UNION ALL
SELECT ID,
       [Option2ID],
       [Option2Name],
       [Option2LName]
FROM   [dbo].[Base]
UNION ALL
SELECT ID,
       [Option3ID],
       [Option3Name],
       [Option3LName]
FROM   [dbo].[Base] 
Martin Smith
la source