Mat*_*thi 6 sql t-sql sql-server sql-server-2008
我有这样的表
Reg_No Student_Name Subject1 Subject2 Subject3 Subject4 Total
----------- -------------------- ----------- ----------- ----------- ----------- -----------
101 Kevin 85 94 78 90 347
102 Andy 75 88 91 78 332
Run Code Online (Sandbox Code Playgroud)
从这里我需要创建一个像这样的临时表或表:
Reg_No Student_Name Subject Total
----------- -------------------- ----------- -----------
101 Kevin 85 347
94
78
90
102 Andy 75 332
88
91
78
Run Code Online (Sandbox Code Playgroud)
有没有办法可以做到这一点SQL Server?
DDL:
DECLARE @temp TABLE
(
Reg_No INT
, Student_Name VARCHAR(20)
, Subject1 INT
, Subject2 INT
, Subject3 INT
, Subject4 INT
, Total INT
)
INSERT INTO @temp (Reg_No, Student_Name, Subject1, Subject2, Subject3, Subject4, Total)
VALUES
(101, 'Kevin', 85, 94, 78, 90, 347),
(102, 'Andy ', 75, 88, 91, 78, 332)
Run Code Online (Sandbox Code Playgroud)
查询#1 - ROW_NUMBER:
SELECT Reg_No = CASE WHEN rn = 1 THEN t.Reg_No END
, Student_Name = CASE WHEN rn = 1 THEN t.Student_Name END
, t.[Subject]
, Total = CASE WHEN rn = 1 THEN t.Total END
FROM (
SELECT
Reg_No
, Student_Name
, [Subject]
, Total
, rn = ROW_NUMBER() OVER (PARTITION BY Reg_No ORDER BY 1/0)
FROM @temp
UNPIVOT
(
[Subject] FOR tt IN (Subject1, Subject2, Subject3, Subject4)
) unpvt
) t
Run Code Online (Sandbox Code Playgroud)
查询#2 - 外部申请:
SELECT t.*
FROM @temp
OUTER APPLY
(
VALUES
(Reg_No, Student_Name, Subject1, Total),
(NULL, NULL, Subject2, NULL),
(NULL, NULL, Subject3, NULL),
(NULL, NULL, Subject4, NULL)
) t(Reg_No, Student_Name, [Subject], Total)
Run Code Online (Sandbox Code Playgroud)
查询计划:

查询成本:

输出:
Reg_No Student_Name Subject Total
----------- -------------------- ----------- -----------
101 Kevin 85 347
NULL NULL 94 NULL
NULL NULL 78 NULL
NULL NULL 90 NULL
102 Andy 75 332
NULL NULL 88 NULL
NULL NULL 91 NULL
NULL NULL 78 NULL
Run Code Online (Sandbox Code Playgroud)
PS:在你的情况下,查询OUTER APPLY比ROW_NUMBER解决方案更快.
检查这个小提琴
;WITH MyCTE AS
(
SELECT *
FROM (
SELECT Reg_No,
[Subject1],
[Subject2],
[Subject3],
[Subject4]
FROM Table1
)p
UNPIVOT
(
Result FOR SubjectName in ([Subject1], [Subject2], [Subject3], [Subject4])
)unpvt
)
SELECT T.Reg_No,
T.Student_Name,
M.SubjectName,
M.Result,
T.Total
FROM Table1 T
JOIN MyCTE M
ON T.Reg_No = M.Reg_No
Run Code Online (Sandbox Code Playgroud)
如果您确实希望其余部分为 NULL 值,您可以尝试以下操作:
这是代码:
;WITH MyCTE AS
(
SELECT *
FROM (
SELECT Reg_No,
[Subject1],
[Subject2],
[Subject3],
[Subject4]
FROM Table1
)p
UNPIVOT
(
Result FOR SubjectName in ([Subject1], [Subject2], [Subject3], [Subject4])
)unpvt
),
MyNumberedCTE AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Reg_No ORDER BY Reg_No,SubjectName) AS RowNum
FROM MyCTE
)
SELECT T.Reg_No,
T.Student_Name,
M.SubjectName,
M.Result,
T.Total
FROM MyCTE M
LEFT JOIN MyNumberedCTE N
ON N.Reg_No = M.Reg_No
AND N.SubjectName = M.SubjectName
AND N.RowNum=1
LEFT JOIN Table1 T
ON T.Reg_No = N.Reg_No
Run Code Online (Sandbox Code Playgroud)