我有以下数据但我不知道之前的表格内容
courses table
-------------
id | name
-------------
7 | math
99 | geology
4 | ethics
5 | sports
33 | english
29 | math boot camp
我需要输出
course1_id | course1_name | course2_id | course2_name | course3_id | course3_name
7 | math | 99 | geology | 4 | ethics
我试过
select case when id = 7 then id end as course1_id,
case when id = 7 then name end as course1_name
from courses
但是返回多行而不是一行,因为我不知道id
我不能使用这种方法。有什么想法吗?
答案 0 :(得分:4)
您需要的SQL是:
SELECT Course1_ID = MAX(CASE WHEN RowNum = 1 THEN ID END),
Course1_Name = MAX(CASE WHEN RowNum = 1 THEN Name END),
Course2_ID = MAX(CASE WHEN RowNum = 2 THEN ID END),
Course2_Name = MAX(CASE WHEN RowNum = 2 THEN Name END),
Course3_ID = MAX(CASE WHEN RowNum = 3 THEN ID END),
Course3_Name = MAX(CASE WHEN RowNum = 3 THEN Name END)
FROM ( SELECT ID,
Name,
RowNum = ROW_NUMBER() OVER(ORDER BY ID)
FROM Courses
) C;
但是对于未知内容,您需要动态生成:
DECLARE @SQL NVARCHAR(MAX) = 'SELECT ' +
STUFF(( SELECT ',Course' + RowNum + '_ID = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN ID END)
,Course' + RowNum + '_Name = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN Name END)'
FROM ( SELECT RowNum = CAST(ROW_NUMBER() OVER(ORDER BY ID) AS VARCHAR(10))
FROM Courses
) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') +
' FROM ( SELECT ID,
Name,
RowNum = ROW_NUMBER() OVER(ORDER BY ID)
FROM Courses
) C;'
EXECUTE SP_EXECUTESQL @SQL;
<强> Example on SQL Fiddle 强>
实现相同结果的另一种方法是:
DECLARE @SQL NVARCHAR(MAX) = '';
SELECT @SQL = @SQL +
',Course' + RowNum + '_ID = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN ID END)
,Course' + RowNum + '_Name = MAX(CASE WHEN RowNum = ' + RowNum + ' THEN Name END)'
FROM ( SELECT RowNum = CAST(ROW_NUMBER() OVER(ORDER BY ID) AS VARCHAR(10))
FROM Courses
) c;
SET @SQL = 'SELECT ' + STUFF(@SQL, 1, 1, '') + '
FROM ( SELECT ID,
Name,
RowNum = ROW_NUMBER() OVER(ORDER BY ID)
FROM Courses
) c;';
EXECUTE SP_EXECUTESQL @SQL;
这将删除昂贵的XML扩展,以将行连接成列
<强> Example on SQL Fiddle 强>
如果课程顺序完全相同,您只需更改ROW_NUMBER
函数中的order by子句。
答案 1 :(得分:0)
我会使用一个支点。因为你没有关于表长度的信息,所以它必须是动态的:
declare @count int;
declare @i int;
declare @p varchar(max) = '';
declare @s varchar(max) = '';
select @count = COUNT(*) from courses;
set @i = 1;
while @i <= @count
begin
set @p = @p + ', [course'+convert(varchar,@i)+'_id], [course'+convert(varchar,@i)+'_name]';
set @i = @i+1;
end
set @p = substring (@p,3,len(@p)-2);
set @s = 'select '+@p+'
from
( select ''course''+convert(varchar,ROW_NUMBER() over (order by convert(int,id)))+''_id'' as rn
, courses.id as c
from courses
union all
select ''course''+convert(varchar,ROW_NUMBER() over (order by convert(int,id)))+''_name'' as rn
, courses.name as c
from courses ) as sourcetable
pivot (
max(c)
for rn in ('+@p+')
) as pivottable';
execute(@s);