Example Schema:
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,)
Is there a way to get results that show up like:
ID | OptionID | OptionName | OptionLName
I have tried to achieve this using UNION ALL but this means going over the same row 3 times in my example, in my real problem I have to do it 10 times. I cannot normalize the table due to legacy code. Is there a way to only go over the Base row once?
You can use `CROSS APPLY ... VALUES` to `UNPIVOT` multiple columns
SELECT ID,
OptionID,
OptionName,
OptionLName
FROM [dbo].[Base]
CROSS APPLY (VALUES([Option1ID], [Option1Name], [Option1LName]),
([Option2ID], [Option2Name], [Option2LName]),
([Option3ID], [Option3Name], [Option3LName]))
V( OptionID, OptionName, OptionLName)
The execution plan for this has one scan of `Base`. The plan is in fact the same as for the 2005 compatible rewrite that uses `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)
But I presume the `UNION ALL` you were trying to avoid was the multiple scans of
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]