T-sql将列的值放入一行

时间:2015-12-03 17:41:12

标签: sql sql-server tsql

假设我有下表

ClassID    StudentID
1          10
1          11
2          12
2          10
3          13

我想要这样的表

ClassID  StudentID1   StudenID2 ...  StudentID32
1        10           11             null
2        12           10             null
3        3            null           null

有没有办法查询上面的表格。约束:每个班级最多可以有32个(可以是任意预定数量)的学生。我想虽然循环可以某种方式使用,但应该有其他方式。

修改 我曾尝试使用Pivot,但我必须使用某种聚合,但对于上述问题,我不必使用任何类型的聚合。在枢轴中我必须命名列(类似in(col1, col2,...)),但在这里我甚至不知道学生的ids。是否有任何通用方法来解决上述简单问题,以便每行代表一个与所有学生一起的唯一ClassID,其中每个StudentID在不同的列中(列可以命名为您喜欢的任何名称),每个ClassID最多可以有32个StudentID(我不应该使用自联接,因为它不实用)

3 个答案:

答案 0 :(得分:1)

我希望我能清楚地理解你。虽然我仍然使用PIVOT,但我认为我也不知道学生证。

    create table Student (
    ClassID INT
    , StudentID INT
)

INSERT INTO Student (ClassID, StudentID) VALUES
 (1,10)
, (1,11)
, (2,12)
, (2,10)
, (3,13)

select
    'Student' + CONVERT(NVARCHAR(150),ROW_NUMBER () OVER (PARTITION BY ClassID ORDER BY StudentID)) AS StudentNo
    , *
into #tmpStud
from Student

declare @distinct nvarchar(max) = ''

/*
option a : flexible to the number of students
*/
--set @distinct = (select distinct '[' + StudentNo + '],' as [text()] from #tmpStud for xml path(''))
--set @distinct = SUBSTRING(@distinct, 0, LEN(@distinct))

/*
option b : max of 32 student
*/
declare @max int = 33
        , @loop int = 1

while (@loop < @max)
    begin
        if(@loop = 1) begin
            set @distinct = @distinct + '[Student' + Convert(nvarchar(20),@loop) + ']'
            set @loop = @loop + 1
        end
        else begin
            set @distinct = @distinct + ',[Student' + Convert(nvarchar(20),@loop) + ']'
            set @loop = @loop + 1
        end
    end

exec ('
select
    *
from (
    select
        ClassID
        , StudentNo
        , StudentID
    FROM #tmpStud
) AS s PIVOT
(
    MAX(StudentID)
    FOR StudentNo IN (' + @distinct + ')
) AS pvt
')

drop table #tmpStud

编辑:有了创建表学生后,请运行以下代码:

select
    'Student' + CONVERT(NVARCHAR(150),ROW_NUMBER () OVER (PARTITION BY ClassID ORDER BY StudentID)) AS StudentNo
    , *
into #tmpStud
from Student

declare @distinct nvarchar(max) = ''

/*
option a : flexible to the number of students
*/
set @distinct = (select distinct '[' + StudentNo + '],' as [text()] from #tmpStud for xml path(''))
set @distinct = SUBSTRING(@distinct, 0, LEN(@distinct))

exec ('
select
    *
from (
    select
        ClassID
        , StudentNo
        , StudentID
    FROM #tmpStud
) AS s PIVOT
(
    MAX(StudentID)
    FOR StudentNo IN (' + @distinct + ')
) AS pvt
')

drop table #tmpStud

编辑:让我们假设您需要32位学生的静态@ max ..使用下面的脚本。

select
    'Student' + CONVERT(NVARCHAR(150),ROW_NUMBER () OVER (PARTITION BY ClassID ORDER BY StudentID)) AS StudentNo
    , *
into #tmpStud
from Student

declare @distinct nvarchar(max) = ''

/*
option b : static max of 32 student
*/
declare @max int = 33
        , @loop int = 1

while (@loop < @max)
    begin
        if(@loop = 1) begin
            set @distinct = @distinct + '[Student' + Convert(nvarchar(20),@loop) + ']'
            set @loop = @loop + 1
        end
        else begin
            set @distinct = @distinct + ',[Student' + Convert(nvarchar(20),@loop) + ']'
            set @loop = @loop + 1
        end
    end

exec ('
select
    *
from (
    select
        ClassID
        , StudentNo
        , StudentID
    FROM #tmpStud
) AS s PIVOT
(
    MAX(StudentID)
    FOR StudentNo IN (' + @distinct + ')
) AS pvt
')

drop table #tmpStud

答案 1 :(得分:0)

如果已知限制相对较小(例如10),则自联接可以正常工作。

(当提问者解释说10不是真正的限制时,答案被移除)

答案 2 :(得分:0)

您需要结合使用Count(),GROUP BY,临时表和PIVOT函数。

上面的示例我有以下内容,它似乎工作。您可以修改Pivot以动态派生列名称,但这需要一些思考。

WITH CTE
     AS (SELECT ClassID,
                COUNT(StudentID) AS StudentNum
         FROM KamTest.dbo.Table1
         GROUP BY ClassID)
     SELECT A.ClassID,
            B.StudentID,
            A.StudentNum INTO #temp
     FROM CTE AS A
     INNER JOIN
     KamTest.dbo.Table1 AS B
     ON A.ClassID=B.ClassID;

SELECT ClassID,
       MAX(StudentID),
       COUNT(StudentID)
FROM KamTest.dbo.Table1
GROUP BY ClassID;

SELECT ClassID,
       [10] AS StudentID10,
       [11] AS StudentID11,
       [12] AS StudentID12,
       [13] AS StudentID13
FROM(
    SELECT ClassID,
           StudentID,
           StudentNum
    FROM #temp) AS SourceTable PIVOT(MAX(StudentNum) FOR StudentID IN([10],
                                                                      [11],
                                                                      [12],
                                                                      [13])) AS PivotTable;

enter image description here