sql server将单行多列放入一列

时间:2013-08-30 07:43:02

标签: sql sql-server sql-server-2008 tsql

我有这样的表

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中执行此操作吗?

5 个答案:

答案 0 :(得分: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 APPLY的查询比ROW_NUMBER解决方案更快。

答案 1 :(得分: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中所有查询的所有行。   UNION操作与使用组合列的连接不同   从两张桌子。

     

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

     

•列的数量和顺序必须相同   查询。

     

•数据类型必须兼容。

答案 2 :(得分:2)

检查this Fiddle

;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值,你可以尝试以下方法:

This is the new Fiddle

以下是代码:

;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

答案 3 :(得分:0)

答案 4 :(得分: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;

有关更多详细信息:Convert row into column when number of row is not fixed