我对以下查询的性能有疑问,是否可以更有效地转动多个相关列。
SELECT
TimetableID,
[Order],
[Time],
[Text],
[1] AS FileID1, Files1.[Filename] AS [File filename1], Files1.[Extension] AS [File extension1], Files1.[Type] AS [File type1], Files1.[Content] AS [File content1],
[2] AS FileID2, Files2.[Filename] AS [File filename2], Files2.[Extension] AS [File extension2], Files2.[Type] AS [File type2], Files2.[Content] AS [File content2],
[3] AS FileID3, Files3.[Filename] AS [File filename3], Files3.[Extension] AS [File extension3], Files3.[Type] AS [File type3], Files3.[Content] AS [File content3],
[4] AS FileID4, Files4.[Filename] AS [File filename4], Files4.[Extension] AS [File extension4], Files4.[Type] AS [File type4], Files4.[Content] AS [File content4],
[5] AS FileID5, Files5.[Filename] AS [File filename5], Files5.[Extension] AS [File extension5], Files5.[Type] AS [File type5], Files5.[Content] AS [File content5],
[6] AS FileID6, Files6.[Filename] AS [File filename6], Files6.[Extension] AS [File extension6], Files6.[Type] AS [File type6], Files6.[Content] AS [File content6],
[7] AS FileID7, Files7.[Filename] AS [File filename7], Files7.[Extension] AS [File extension7], Files7.[Type] AS [File type7], Files7.[Content] AS [File content7],
[8] AS FileID8, Files8.[Filename] AS [File filename8], Files8.[Extension] AS [File extension8], Files8.[Type] AS [File type8], Files8.[Content] AS [File content8],
[9] AS FileID9, Files9.[Filename] AS [File filename9], Files9.[Extension] AS [File extension9], Files9.[Type] AS [File type9], Files9.[Content] AS [File content9],
[10] AS FileID10, Files10.[Filename] AS [File filename10], Files10.[Extension] AS [File extension10], Files10.[Type] AS [File type10], Files10.[Content] AS [File content10],
[11] AS FileID11, Files11.[Filename] AS [File filename11], Files11.[Extension] AS [File extension11], Files11.[Type] AS [File type11], Files11.[Content] AS [File content11],
[12] AS FileID12, Files12.[Filename] AS [File filename12], Files12.[Extension] AS [File extension12], Files12.[Type] AS [File type12], Files12.[Content] AS [File content12],
[13] AS FileID13, Files13.[Filename] AS [File filename13], Files13.[Extension] AS [File extension13], Files13.[Type] AS [File type13], Files13.[Content] AS [File content13],
[14] AS FileID14, Files14.[Filename] AS [File filename14], Files14.[Extension] AS [File extension14], Files14.[Type] AS [File type14], Files14.[Content] AS [File content14],
[15] AS FileID15, Files15.[Filename] AS [File filename15], Files15.[Extension] AS [File extension15], Files15.[Type] AS [File type15], Files15.[Content] AS [File content15],
[16] AS FileID16, Files16.[Filename] AS [File filename16], Files16.[Extension] AS [File extension16], Files16.[Type] AS [File type16], Files16.[Content] AS [File content16],
[17] AS FileID17, Files17.[Filename] AS [File filename17], Files17.[Extension] AS [File extension17], Files17.[Type] AS [File type17], Files17.[Content] AS [File content17],
[18] AS FileID18, Files18.[Filename] AS [File filename18], Files18.[Extension] AS [File extension18], Files18.[Type] AS [File type18], Files18.[Content] AS [File content18],
[19] AS FileID19, Files19.[Filename] AS [File filename19], Files19.[Extension] AS [File extension19], Files19.[Type] AS [File type19], Files19.[Content] AS [File content19],
[20] AS FileID20, Files20.[Filename] AS [File filename20], Files20.[Extension] AS [File extension20], Files20.[Type] AS [File type20], Files20.[Content] AS [File content20]
FROM
(
SELECT
t.[TimetableID],
t.[Order],
t.[Time],
t.[Text],
tf.N,
tf.FileID
FROM
dbo.Timetables AS t
LEFT JOIN
dbo.Timetable_Files AS tf
ON
tf.TimetableID = t.TimetableID
) AS [source]
PIVOT
(
MAX(FileID) FOR N IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15], [16], [17], [18], [19], [20])
) AS [fid]
LEFT JOIN dbo.Files AS Files1 ON Files1.FileID = fid.[1]
LEFT JOIN dbo.Files AS Files2 ON Files2.FileID = fid.[2]
LEFT JOIN dbo.Files AS Files3 ON Files3.FileID = fid.[3]
LEFT JOIN dbo.Files AS Files4 ON Files4.FileID = fid.[4]
LEFT JOIN dbo.Files AS Files5 ON Files5.FileID = fid.[5]
LEFT JOIN dbo.Files AS Files6 ON Files6.FileID = fid.[6]
LEFT JOIN dbo.Files AS Files7 ON Files7.FileID = fid.[7]
LEFT JOIN dbo.Files AS Files8 ON Files8.FileID = fid.[8]
LEFT JOIN dbo.Files AS Files9 ON Files9.FileID = fid.[9]
LEFT JOIN dbo.Files AS Files10 ON Files10.FileID = fid.[10]
LEFT JOIN dbo.Files AS Files11 ON Files11.FileID = fid.[11]
LEFT JOIN dbo.Files AS Files12 ON Files12.FileID = fid.[12]
LEFT JOIN dbo.Files AS Files13 ON Files13.FileID = fid.[13]
LEFT JOIN dbo.Files AS Files14 ON Files14.FileID = fid.[14]
LEFT JOIN dbo.Files AS Files15 ON Files15.FileID = fid.[15]
LEFT JOIN dbo.Files AS Files16 ON Files16.FileID = fid.[16]
LEFT JOIN dbo.Files AS Files17 ON Files17.FileID = fid.[17]
LEFT JOIN dbo.Files AS Files18 ON Files18.FileID = fid.[18]
LEFT JOIN dbo.Files AS Files19 ON Files19.FileID = fid.[19]
LEFT JOIN dbo.Files AS Files20 ON Files20.FileID = fid.[20]
我有以下表结构:
T_Timetable中的每个条目都可以附加多个文件。这是通过T_Timetable_File表实现的。
我创建了一个视图,为分配表中的每个条目分配一个递增的行号。时间表中每个条目最多有20个文件。
CREATE VIEW
dbo.Timetable_Files
AS
SELECT
TimetableID,
FileID,
ROW_NUMBER() over(PARTITION BY TimetableID ORDER BY FileID ASC) AS N
FROM
dbo.T_Timetable_File
我需要以下面的格式输出结果,问题顶部的查询已经完成。
此查询的问题是SQL Server分配给它的内存量。虽然当所有时间表条目包含最多20个文件时,查询可能会返回大量数据,但大多数情况下,条目没有连接到最多5个文件。因此,它也会引发“过度记忆补助”警告。
我对加入“文件”视图的解决方案(视图只是用于以后权限管理的表的所有列的选择)也不太满意20次,以获取20个可能的附加文件的所有文件信息。
CREATE VIEW
dbo.Files
AS
SELECT
ID AS FileID,
[Filename],
Extension,
[Type],
Content
FROM
dbo.T_File
我的问题:是否有更好/更快,更优雅的方式来转动每个文件条目的5列?
编辑:与此同时,我在这里找到了一些东西:
Using pivot and unpivot to pivot multiple columns
使用此信息,我将查询重写为如下所示:
WITH CTE AS
(
SELECT
t.[TimetableID],
t.[Order],
t.[Time],
t.[Text],
N,
CONVERT(varbinary(MAX), f.FileID) AS FileID, /* f.Content is varbinary, so to unpivot the other columns they have to converted to varbinary, too */
CONVERT(varbinary(MAX), f.[Filename]) AS [Filename],
CONVERT(varbinary(MAX), f.Extension) AS Extension,
CONVERT(varbinary(MAX), f.[Type]) AS [Type],
f.Content
FROM
dbo.Timetables AS t
LEFT JOIN
dbo.Timetable_Files AS tf
ON
tf.TimetableID = t.TimetableID
LEFT JOIN
dbo.Files AS f
ON
f.FileID = tf.FileID
)
SELECT
TimetableID,
[Order],
[Time],
[Text],
CONVERT(int, FileID1) AS FileID1, CONVERT(varchar(400), Filename1) AS Filename1, CONVERT(varchar(400), Extension1) AS Extension1, CONVERT(varchar(400), Type1) AS Type1, Content1, /*Convert the other columns back to their original type*/
CONVERT(int, FileID2) AS FileID2, CONVERT(varchar(400), Filename2) AS Filename2, CONVERT(varchar(400), Extension2) AS Extension2, CONVERT(varchar(400), Type2) AS Type2, Content2,
CONVERT(int, FileID3) AS FileID3, CONVERT(varchar(400), Filename3) AS Filename3, CONVERT(varchar(400), Extension3) AS Extension3, CONVERT(varchar(400), Type3) AS Type3, Content3,
CONVERT(int, FileID4) AS FileID4, CONVERT(varchar(400), Filename4) AS Filename4, CONVERT(varchar(400), Extension4) AS Extension4, CONVERT(varchar(400), Type4) AS Type4, Content4,
CONVERT(int, FileID5) AS FileID5, CONVERT(varchar(400), Filename5) AS Filename5, CONVERT(varchar(400), Extension5) AS Extension5, CONVERT(varchar(400), Type5) AS Type5, Content5,
CONVERT(int, FileID6) AS FileID6, CONVERT(varchar(400), Filename6) AS Filename6, CONVERT(varchar(400), Extension6) AS Extension6, CONVERT(varchar(400), Type6) AS Type6, Content6,
CONVERT(int, FileID7) AS FileID7, CONVERT(varchar(400), Filename7) AS Filename7, CONVERT(varchar(400), Extension7) AS Extension7, CONVERT(varchar(400), Type7) AS Type7, Content7,
CONVERT(int, FileID8) AS FileID8, CONVERT(varchar(400), Filename8) AS Filename8, CONVERT(varchar(400), Extension8) AS Extension8, CONVERT(varchar(400), Type8) AS Type8, Content8,
CONVERT(int, FileID9) AS FileID9, CONVERT(varchar(400), Filename9) AS Filename9, CONVERT(varchar(400), Extension9) AS Extension9, CONVERT(varchar(400), Type9) AS Type9, Content9,
CONVERT(int, FileID10) AS FileID10, CONVERT(varchar(400), Filename10) AS Filename10, CONVERT(varchar(400), Extension10) AS Extension10, CONVERT(varchar(400), Type10) AS Type10, Content10,
CONVERT(int, FileID11) AS FileID11, CONVERT(varchar(400), Filename11) AS Filename11, CONVERT(varchar(400), Extension11) AS Extension11, CONVERT(varchar(400), Type11) AS Type11, Content11,
CONVERT(int, FileID12) AS FileID12, CONVERT(varchar(400), Filename12) AS Filename12, CONVERT(varchar(400), Extension12) AS Extension12, CONVERT(varchar(400), Type12) AS Type12, Content12,
CONVERT(int, FileID13) AS FileID13, CONVERT(varchar(400), Filename13) AS Filename13, CONVERT(varchar(400), Extension13) AS Extension13, CONVERT(varchar(400), Type13) AS Type13, Content13,
CONVERT(int, FileID14) AS FileID14, CONVERT(varchar(400), Filename14) AS Filename14, CONVERT(varchar(400), Extension14) AS Extension14, CONVERT(varchar(400), Type14) AS Type14, Content14,
CONVERT(int, FileID15) AS FileID15, CONVERT(varchar(400), Filename15) AS Filename15, CONVERT(varchar(400), Extension15) AS Extension15, CONVERT(varchar(400), Type15) AS Type15, Content15,
CONVERT(int, FileID16) AS FileID16, CONVERT(varchar(400), Filename16) AS Filename16, CONVERT(varchar(400), Extension16) AS Extension16, CONVERT(varchar(400), Type16) AS Type16, Content16,
CONVERT(int, FileID17) AS FileID17, CONVERT(varchar(400), Filename17) AS Filename17, CONVERT(varchar(400), Extension17) AS Extension17, CONVERT(varchar(400), Type17) AS Type17, Content17,
CONVERT(int, FileID18) AS FileID18, CONVERT(varchar(400), Filename18) AS Filename18, CONVERT(varchar(400), Extension18) AS Extension18, CONVERT(varchar(400), Type18) AS Type18, Content18,
CONVERT(int, FileID19) AS FileID19, CONVERT(varchar(400), Filename19) AS Filename19, CONVERT(varchar(400), Extension19) AS Extension19, CONVERT(varchar(400), Type19) AS Type19, Content19,
CONVERT(int, FileID20) AS FileID20, CONVERT(varchar(400), Filename20) AS Filename20, CONVERT(varchar(400), Extension20) AS Extension20, CONVERT(varchar(400), Type20) AS Type20, Content20
FROM
(
SELECT
TimetableID,
[Order],
[Time],
[Text],
Variable + CONVERT(varchar(2), ISNULL(N, '0')) AS [Variable], /* Without the ISNULL timetable entries without files will not be displayed */
[Value]
FROM
(
SELECT
TimetableID,
[Order],
[Time],
[Text],
N,
ISNULL(FileID, 0x0) AS FileID,
[Filename],
Extension,
[Type],
[Content]
FROM
CTE
GROUP BY
TimetableID,
[Order],
[Time],
[Text],
N,
FileID,
[Filename],
Extension,
[Type],
[Content]
) AS origresult
UNPIVOT
(
[Value] FOR Variable IN (FileID, [Filename], Extension, [Type], [Content])
) AS unpiv
) AS intermediateresult
PIVOT
(
MAX([Value]) FOR Variable IN
(
FileID1, Filename1, Extension1, Type1, Content1,
FileID2, Filename2, Extension2, Type2, Content2,
FileID3, Filename3, Extension3, Type3, Content3,
FileID4, Filename4, Extension4, Type4, Content4,
FileID5, Filename5, Extension5, Type5, Content5,
FileID6, Filename6, Extension6, Type6, Content6,
FileID7, Filename7, Extension7, Type7, Content7,
FileID8, Filename8, Extension8, Type8, Content8,
FileID9, Filename9, Extension9, Type9, Content9,
FileID10, Filename10, Extension10, Type10, Content10,
FileID11, Filename11, Extension11, Type11, Content11,
FileID12, Filename12, Extension12, Type12, Content12,
FileID13, Filename13, Extension13, Type13, Content13,
FileID14, Filename14, Extension14, Type14, Content14,
FileID15, Filename15, Extension15, Type15, Content15,
FileID16, Filename16, Extension16, Type16, Content16,
FileID17, Filename17, Extension17, Type17, Content17,
FileID18, Filename18, Extension18, Type18, Content18,
FileID19, Filename19, Extension19, Type19, Content19,
FileID20, Filename20, Extension20, Type20, Content20
)
) AS piv
首先使用unpivot为我做了诀窍。该查询不会生成内存警告并且执行速度更快,因为它只访问File表一次(根据SQL Server统计信息)。
我还将尝试larnu建议的方法并比较执行的速度。谢谢到目前为止。