Есть ли лучший вариант, чем Union All, для множественного выбора из одной строки?

10

Пример схемы:

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,)

Есть ли способ получить результаты, которые отображаются как:

ID | OptionID | OptionName | OptionLName

Я пытался добиться этого с помощью UNION ALL, но в моем примере это означает, что нужно повторить одну и ту же строку 3 раза, в моей настоящей задаче я должен сделать это 10 раз. Я не могу нормализовать таблицу из-за устаревшего кода. Есть ли способ пройти через Базовый ряд только один раз?

JustinDoesWork
источник

Ответы:

23

Вы можете использовать CROSS APPLY ... VALUESдля UNPIVOTнескольких столбцов

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

План выполнения для этого имеет одно сканирование Base. План на самом деле такой же, как и для 2005-совместимого переписывания, которое используетUNION 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)  

Но я полагаю, что UNION ALLвы пытались избежать многократного сканирования

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] 
Мартин Смит
источник