6

我有这样的桌子

Reg_No      Student_Name         Subject1    Subject2    Subject3    Subject4    Total
----------- -------------------- ----------- ----------- ----------- ----------- -----------
101         Kevin                85          94          78          90          347
102         Andy                 75          88          91          78          332

从这里我需要创建一个临时表或这样的表:

Reg_No      Student_Name         Subject     Total
----------- -------------------- ----------- -----------
101         Kevin                85          347
                                 94           
                                 78           
                                 90           
102         Andy                 75          332
                                 88           
                                 91           
                                 78           

有没有办法我可以做到这一点SQL Server

4

5 回答 5

5

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)

查询 #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

查询 #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)

查询计划:

tt

查询费用:

tt2

输出:

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

PS:在您的情况下,查询OUTER APPLYROW_NUMBER解决方案更快。

于 2013-08-30T07:50:03.807 回答
4

最简单的方法是使用UNION子句

select Reg_No, Student_Name, Subject1, Total from YourTable union all
select Reg_No, Student_Name, Subject2, Total from YourTable union all
select Reg_No, Student_Name, Subject3, Total from YourTable union all
select Reg_No, Student_Name, Subject3, Total from YourTable

联盟

将两个或多个查询的结果组合成一个结果集,其中包括属于联合中所有查询的所有行。UNION 操作不同于使用结合来自两个表的列的连接。

以下是使用 UNION 组合两个查询的结果集的基本规则:

• 在所有查询中,列的数量和顺序必须相同。

• 数据类型必须兼容。

于 2013-08-30T07:47:21.243 回答
2

检查这个小提琴

;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

如果您确实想要其余的 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
于 2013-08-30T07:56:40.057 回答
0

您应该照顾 PIVOT 运算符:

http://technet.microsoft.com/en-us/library/ms177410(v=sql.100).aspx

于 2013-08-30T07:50:03.563 回答
0
> DECLARE  @cols AS NVARCHAR(MAX),@query  AS NVARCHAR(MAX)
> 
>  select @cols = STUFF((SELECT ',' + QUOTENAME(designation) 
>                      from MyTable
>                      group by designation  
>                      order by designation
>              FOR XML PATH(''), TYPE
>              ).value('.', 'NVARCHAR(MAX)'),1,1,'') 
> 
>  set @query = N'SELECT Row, ' + @cols + N' from 
>               (
>                  select ''SS'' Row, SS AS Value , designation from MyTable
>                  UNION ALL
>                  select  ''AS'' Row, [AS] AS Value , designation from MyTable
>                  UNION ALL 
>                  select  ''Vac'' Row, Vac AS Value , designation from MyTable 
>              ) x
>              pivot 
>              (
>                  max(Value) for designation in (' + @cols + N')
>              ) p '                    
>      exec sp_executesql @query;

有关更多详细信息:当行数不固定时将行转换为列

于 2020-02-26T08:18:42.637 回答