这个问题存在一些限制;我没有能力从根本上改变任何数据库结构。
这里的挑战是我在数据库中有行,其中包含真正应该在其自己行上的信息。列结构的一个简化示例:
[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
由于我使用它来生成视图,因此我必须为每组guest列引用相同的表,并使用UNION ALLs
将它们绑定在一起。
然而,从那时起,我不得不在派生视图之上构建日益复杂的查询。每一层复杂性都会导致结果返回的速度越来越慢。
我采取了一种根本不好的方法吗?是否有其他更正确的方法以我需要的方式建模数据?
这是实际查询的一部分,因此您可以看到我正在处理的内容:
--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")
答案 0 :(得分:2)
取决于您要对视图执行的操作。
视图查询必须在您对其执行的任何操作之前执行。因此,如果您正在处理仅处理视图返回的结果的10%的事情,则会浪费处理。执行的操作可能与视图中已存在的逻辑同时完成。
可以在必要时添加索引吗?那会有所帮助......
物化视图,称为indexed view in SQL Server terminology,是一种可行的可能性,但众所周知是不适应的。
答案 1 :(得分:2)
您是否考虑过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
在一个选择中使用多个unpiv是很棘手的;我从这些家伙那里得到了上述观点:
http://weblogs.sqlteam.com/jeffs/archive/2008/04/23/unpivot.aspx http://mangalpardeshi.blogspot.com/2009/04/unpivot-multiple-columns.html
重要的是要注意标记为“棘手”的部分将在重复列的名称中以不同的位数(例如FirstName11和FirstName1将成为问题)中断。你可以使用一些substring()技巧来解决这个问题。可能不是最好的主意,但是......
另外,2月22日:这是关于unpivot的现场文章:http://bradsruminations.blogspot.com/2010/02/spotlight-on-unpivot-part-1.html
答案 2 :(得分:1)
以下是我实施上述答案的结果。希望这对接下来遇到类似挑战的任何人都有帮助。
从概念上讲,UNPIVOT运营商正是我正在努力完成的模型。如果没有某种实施限制会使我无法使用它,还有待观察。由于我有很多列要“解压缩”,因此使用UNPIVOT运算符有两种基本方法。 (1)我可以为相关的每个列运行一个单独的UNPIVOT,或者(2),我可以运行一个UNPIVOT然后根据有条件地计算其余的列结果。我选择了第二种方法,因为它对我来说更容易掌握,但我仍然有兴趣在将来测试这两种方法。
由此产生的查询仍然是不重复的重复(它必须一遍又一遍地保持相同的十条件情况块),但与我最初使用的怪物相比,它的难以置信的简化。 最重要的是,当我按照旧查询运行时,它只占总查询成本的9%,而旧查询的成本只有91%。所以它似乎也更有效率
这是重新设计的查询(仍然很长,但可能只有旧查询长度的20%左右)
SELECT
Case(FN) WHEN 'FirstName' THEN 'Primary' ELSE 'Guest' END as RegType,
(Case(FN) WHEN 'FirstName' THEN 0
WHEN 'FF_27637_1' THEN 1
WHEN 'FF_27742_1' THEN 2
WHEN 'FF_27638_1' THEN 3
WHEN 'FF_27639_1' THEN 4
WHEN 'FF_27640_1' THEN 5
WHEN 'FF_27641_1' THEN 6
WHEN 'FF_27642_1' THEN 7
WHEN 'FF_27643_1' THEN 8
WHEN 'FF_27644_1' THEN 9
WHEN 'FF_27645_1' THEN 10 END) as GuestNo,
Confirmation,
FirstNames as FirstName,
(Case(FN) WHEN 'FirstName' THEN LastName
WHEN 'FF_27637_1' THEN FF_27637_152806
WHEN 'FF_27742_1' THEN FF_27742_153577
WHEN 'FF_27638_1' THEN FF_27638_152814
WHEN 'FF_27639_1' THEN FF_27639_152817
WHEN 'FF_27640_1' THEN FF_27640_152852
WHEN 'FF_27641_1' THEN FF_27641_152860
WHEN 'FF_27642_1' THEN FF_27642_152868
WHEN 'FF_27643_1' THEN FF_27643_152877
WHEN 'FF_27644_1' THEN FF_27644_152885
WHEN 'FF_27645_1' THEN FF_27645_152893 END) as LastName,
(Case(FN) WHEN 'FirstName' THEN Email
WHEN 'FF_27637_1' THEN FF_27637_152807
WHEN 'FF_27742_1' THEN FF_27742_153578
WHEN 'FF_27638_1' THEN FF_27638_152815
WHEN 'FF_27639_1' THEN FF_27639_152818
WHEN 'FF_27640_1' THEN FF_27640_152853
WHEN 'FF_27641_1' THEN FF_27641_152861
WHEN 'FF_27642_1' THEN FF_27642_152869
WHEN 'FF_27643_1' THEN FF_27643_152878
WHEN 'FF_27644_1' THEN FF_27644_152886
WHEN 'FF_27645_1' THEN FF_27645_152894 END) as Email,
(Case(FN) WHEN 'FirstName' THEN HotelCheckOut
WHEN 'FF_27637_1' THEN FF_27637_152821
WHEN 'FF_27742_1' THEN FF_27645_152896
WHEN 'FF_27638_1' THEN FF_27742_153580
WHEN 'FF_27639_1' THEN FF_27638_152847
WHEN 'FF_27640_1' THEN FF_27639_152842
WHEN 'FF_27641_1' THEN FF_27640_152855
WHEN 'FF_27642_1' THEN FF_27641_152863
WHEN 'FF_27643_1' THEN FF_27642_152871
WHEN 'FF_27644_1' THEN FF_27643_152880
WHEN 'FF_27645_1' THEN FF_27644_152888 END) as HotelChoice,
(Case(FN) WHEN 'FirstName' THEN HotelCheckIn
WHEN 'FF_27637_1' THEN FF_27637_152813
WHEN 'FF_27742_1' THEN FF_27742_153579
WHEN 'FF_27638_1' THEN FF_27638_152816
WHEN 'FF_27639_1' THEN FF_27639_152819
WHEN 'FF_27640_1' THEN FF_27640_152854
WHEN 'FF_27641_1' THEN FF_27641_152862
WHEN 'FF_27642_1' THEN FF_27642_152870
WHEN 'FF_27643_1' THEN FF_27643_152879
WHEN 'FF_27644_1' THEN FF_27644_152887
WHEN 'FF_27645_1' THEN FF_27645_152895 END) as HotelCheckIn,
(Case(FN) WHEN 'FirstName' THEN HotelCheckOut
WHEN 'FF_27637_1' THEN FF_27637_152821
WHEN 'FF_27742_1' THEN FF_27742_153580
WHEN 'FF_27638_1' THEN FF_27638_152847
WHEN 'FF_27639_1' THEN FF_27639_152842
WHEN 'FF_27640_1' THEN FF_27640_152855
WHEN 'FF_27641_1' THEN FF_27641_152863
WHEN 'FF_27642_1' THEN FF_27642_152871
WHEN 'FF_27643_1' THEN FF_27643_152880
WHEN 'FF_27644_1' THEN FF_27644_152888
WHEN 'FF_27645_1' THEN FF_27645_152896 END) as HotelCheckOut,
(Case(FN) WHEN 'FirstName' THEN HotelRoomPreference
WHEN 'FF_27637_1' THEN FF_27637_152823
WHEN 'FF_27742_1' THEN FF_27742_153582
WHEN 'FF_27638_1' THEN FF_27638_152849
WHEN 'FF_27639_1' THEN FF_27639_152844
WHEN 'FF_27640_1' THEN FF_27640_152857
WHEN 'FF_27641_1' THEN FF_27641_152865
WHEN 'FF_27642_1' THEN FF_27642_152874
WHEN 'FF_27643_1' THEN FF_27643_152882
WHEN 'FF_27644_1' THEN FF_27644_152890
WHEN 'FF_27645_1' THEN FF_27645_152898 END) as RoomType,
(Case(FN) WHEN 'FirstName' THEN HotelSmoking
WHEN 'FF_27637_1' THEN FF_27637_152824
WHEN 'FF_27742_1' THEN FF_27742_153583
WHEN 'FF_27638_1' THEN FF_27638_152850
WHEN 'FF_27639_1' THEN FF_27639_152845
WHEN 'FF_27640_1' THEN FF_27640_152858
WHEN 'FF_27641_1' THEN FF_27641_152866
WHEN 'FF_27642_1' THEN FF_27642_152875
WHEN 'FF_27643_1' THEN FF_27643_152883
WHEN 'FF_27644_1' THEN FF_27644_152891
WHEN 'FF_27645_1' THEN FF_27645_152899 END) as Smoking,
(Case(FN) WHEN 'FirstName' THEN NULL
WHEN 'FF_27637_1' THEN FF_27637_154245
WHEN 'FF_27742_1' THEN FF_27742_154247
WHEN 'FF_27638_1' THEN FF_27638_154249
WHEN 'FF_27639_1' THEN FF_27639_154251
WHEN 'FF_27640_1' THEN FF_27640_154253
WHEN 'FF_27641_1' THEN FF_27641_154255
WHEN 'FF_27642_1' THEN FF_27642_154257
WHEN 'FF_27643_1' THEN FF_27643_154259
WHEN 'FF_27644_1' THEN FF_27644_154261
WHEN 'FF_27645_1' THEN FF_27645_154263 END) as SharingWith,
FROM Event
UNPIVOT (FirstNames for FN in (FirstName, FF_27637_1, FF_27742_1, FF_27638_1, FF_27639_1, FF_27640_1, FF_27641_1, FF_27642_1, FF_27643_1, FF_27644_1, FF_27645_1)) as FirstNames
WHERE Audience = 'Primary' and Submitted = 1 and Cancelled = 0 and Type = 'Production' ORDER BY Confirmation
作为旁注,如果我尝试将其作为视图运行,则会收到不支持UNPIVOT的错误。如果我在视图中放置相同的内容并将其作为派生表 - SELECT * FROM (...query...)
) - ,我在Studio Manager中收到相同的警告,但它返回结果就好了。怪异。
再次感谢您的所有答案。