假设我有下表
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(我不应该使用自联接,因为它不实用)
答案 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;