这个问题有一些限制;我没有能力从根本上改变任何数据库结构。
这里的挑战是数据库中的一些行包含真正应该位于其自己的行中的信息。列结构的简化示例:
[PersonID] [FirstName] [LastName] [FirstNameGuest1] [LastNameGuest1]
1 Ringo Starr John Lennon
2 George Harrison Paul McCartney
我需要像这样将它们分开,以便能够运行我需要的报告:
[PersonID] [FirstName] [LastName]
1 Ringo Starr
1 John Lennon
2 George Harrison
2 Paul McCartney
由于我使用它来生成 View ,因此我必须为每组 guest 列引用相同的表,并使用 UNION ALL
将它们全部连接在一起。
但是,从那时起,我不得不在派生 View 之上构建日益复杂的查询。每一层的复杂性都会导致结果返回的速度越来越慢。
我采取的方法从根本上来说是错误的吗?还有其他更正确的方法来按照我需要的方式对数据进行建模吗?
这是实际查询的一部分,以便您可以看到我正在处理的内容:
--Primary Record
SELECT
'Franchisee' AS 'Type',
Confirmation AS 'BelongingTo',
0 AS 'GuestNo',
FirstName,
LastName,
FF_27557_152972 AS 'HotelChoice',
HotelCheckIn,
HotelCheckOut,
HotelSmoking AS 'Smoking',
(CASE FF_27554_1 WHEN 'Yes' THEN 1 ELSE 0 END) AS 'PrimaryRoomHolder',
'' AS 'SharingWith',
'None' AS 'SharingWithName'
FROM dbo.[Table]
WHERE Type = 'Production' AND Submitted = 1 AND Cancelled = 0 AND Label = 'Primary'
UNION ALL
-- First Guest
SELECT
'Guest' AS 'Type',
Confirmation AS 'BelongingTo',
1 AS 'GuestNo',
FF_27637_1 AS 'FirstName',
FF_27637_152806 AS 'LastName',
FF_27637_152822 AS 'HotelChoice',
FF_27637_152813 AS 'HotelCheckIn',
FF_27637_152821 AS 'HotelCheckOut',
FF_27637_152824 AS 'Smoking',
(CASE WHEN FF_27637_152822 IS NOT NULL THEN 1 ELSE 0 END) AS 'PrimaryRoomHolder',
FF_27637_154245 AS 'SharingWith',
(CASE CAST(FF_27637_154245 AS integer)
WHEN 0 THEN FirstName + ' ' + LastName
WHEN 1 THEN FF_27637_1 + ' ' + FF_27637_152806
WHEN 2 THEN FF_27742_1 + ' ' + FF_27742_153577
WHEN 3 THEN FF_27638_1 + ' ' + FF_27638_152814
WHEN 4 THEN FF_27639_1 + ' ' + FF_27639_152817
WHEN 5 THEN FF_27640_1 + ' ' + FF_27640_152852
WHEN 6 THEN FF_27641_1 + ' ' + FF_27641_152860
WHEN 7 THEN FF_27642_1 + ' ' + FF_27642_152868
WHEN 8 THEN FF_27643_1 + ' ' + FF_27643_152877
WHEN 9 THEN FF_27644_1 + ' ' + FF_27644_152885
WHEN 10 THEN FF_27645_1 + ' ' + FF_27645_152893
ELSE 'None' END) AS 'SharingWithName'
FROM dbo.Event_213_1546 AS Event_213_1546_10
WHERE Type = 'Production' AND Submitted = 1 AND Cancelled = 0 AND Label = 'Primary' AND FF_27637_1 IS NOT NULL
.
.
.
(Iterates through 9 more guests exactly like "First Guest")
最佳答案
您考虑过 UNPIVOT 运算符吗?它做同样的事情,但可能不那么痛苦(也许!:-)。需要 2005 年或更高版本。
http://blogs.msdn.com/craigfr/archive/2007/07/17/the-unpivot-operator.aspx
示例:
declare @names table ( personid int,
firstname1 varchar(50),
lastname1 varchar(50),
firstname2 varchar(50),
lastname2 varchar(50),
firstname3 varchar(50),
lastname3 varchar(50)
-- <etc.>
)
Insert @names values ( 1, 'Fred', 'Flintstone', 'Barney', 'Rubble', 'Wilma', 'Flintstone' )
Insert @names values ( 2, 'Super', 'Man', 'Aqua', 'Man', 'Wonder', 'Woman' )
select * from @names
select personid, firstnamecol, firstname, lastnamecol, lastname
from @names
unpivot( firstname for firstnamecol in ( firstname1, firstname2, firstname3 ) ) firstnames
unpivot( lastname for lastnamecol in ( lastname1, lastname2, lastname3 ) ) lastnames
where right(firstnamecol, 1) = right( lastnamecol, 1 ) -- This is the tricky bit
在一次选择中使用多个逆透视是很棘手的;我从这些人那里得到了上述想法:
http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx http://mangalpardeshi.blogspot.com/2009/04/unpivot-multiple-columns.html
需要注意的是,标记为“tricky”的部分将因重复列名称中不同位数的数字而中断(例如,FirstName11 和 FirstName1 将成为问题)。您可以使用一些 substring() 技巧来解决这个问题。可能不是最好的主意,但是......
补充,2 月 22 日:这是一篇有关 unpivot 的精彩文章:http://bradsruminations.blogspot.com/2010/02/spotlight-on-unpivot-part-1.html
关于sql - 使用多个UNION ALL构建 View : is there a better way?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2240332/