Sql 使用GroupBy获取PIVOT
我有这张桌子:Sql 使用GroupBy获取PIVOT,sql,sql-server,sql-server-2008,pivot,pivot-table,Sql,Sql Server,Sql Server 2008,Pivot,Pivot Table,我有这张桌子: Person Job Day EndDay 1 101 1 12 1 102 2 11 1 103 3 11 3 101 1 11 3 102 2 11 3 JobOff 3 11 2 101 1 11 2 1
Person Job Day EndDay
1 101 1 12
1 102 2 11
1 103 3 11
3 101 1 11
3 102 2 11
3 JobOff 3 11
2 101 1 11
2 102 2 11
2 103 3 11
2 JobOff 4 11
...
Day (Columns)
Person (Rows)
Person 1 2 3 4
1 101 102 103 N/A
2 101 102 103 JobOff
3 101 102 JobOff N/A
附言:我的日子快到N了,我不知道。因此,静态SQL在这里是不可行的
我需要将其更改为以下形式:
Person Job Day EndDay
1 101 1 12
1 102 2 11
1 103 3 11
3 101 1 11
3 102 2 11
3 JobOff 3 11
2 101 1 11
2 102 2 11
2 103 3 11
2 JobOff 4 11
...
Day (Columns)
Person (Rows)
Person 1 2 3 4
1 101 102 103 N/A
2 101 102 103 JobOff
3 101 102 JobOff N/A
任何帮助都将不胜感激。我对SQL非常陌生
多亏了Roman,我有了这个S.程序:
CREATE PROCEDURE [dbo].[MyStoredProcedure] AS
BEGIN
declare @stmt nvarchar(max)
select @stmt =
isnull(@stmt + ', ', '') +
'isnull(max(case when [Day] = ' + cast([Day_I] as nvarchar(max)) +
' then Job end), ''N/A'') as [' + cast([Day_I] as nvarchar(max)) + ']'
from (select distinct [Day_I] from dbo.Solution) as t
order by [Day_I]
select @stmt = '
select
Person_I, ' + @stmt +'
from dbo.Solution_Format
group by Person_I'
END
但是当我像这样执行这个存储过程时:
exec MyStoredProcedure
它没有显示任何结果。没有错误 一种方法是使用多个自联接
Select
t1.Person,
COALESCE(t1.Job, 'N/A') [1],
COALESCE(t2.Job, 'N/A' )[2],
COALESCE(t3.Job, 'N/A') [3],
COALESCE(t4.Job, 'N/A') [4]
FROM
table1 t1
LEFT JOIN table1 t2
ON t1.Person = t2.Person
and t2.Day = 2
LEFT JOIN table1 t3
ON t1.Person = t3.Person
and t3.Day = 3
LEFT JOIN table1 t4
ON t1.Person = t4.Person
and t4.Day = 4
WHERE
t1.Day = 1
ORDER BY
t1.Person
另一种方法是使用MAX(CASE),但我不喜欢这样使用聚合
Select
t1.Person,
COALESCE(MAX(CASE WHEN t1.Day = 1 then t1.Job END), 'N/A') [1],
COALESCE(MAX(CASE WHEN t1.Day = 2 then t1.Job END), 'N/A') [2],
COALESCE(MAX(CASE WHEN t1.Day = 3 then t1.Job END), 'N/A') [3],
COALESCE(MAX(CASE WHEN t1.Day = 4 then t1.Job END), 'N/A') [4]
FROM
table1 t1
GROUP BY
t1.Person
最后是pivot子句,我不太喜欢,因为这里的MAX
SELECT person,
COALESCE([1], 'N/A') [1],
COALESCE([2], 'N/A') [2],
COALESCE([3], 'N/A') [3],
COALESCE([4], 'N/A') [4]
FROM (SELECT t1.person,
t1.day,
t1.job
FROM table1 t1) p
PIVOT (Max (job)
FOR day IN ( [1],
[2],
[3],
[4]) ) AS pvt
一种方法是使用多个自联接
Select
t1.Person,
COALESCE(t1.Job, 'N/A') [1],
COALESCE(t2.Job, 'N/A' )[2],
COALESCE(t3.Job, 'N/A') [3],
COALESCE(t4.Job, 'N/A') [4]
FROM
table1 t1
LEFT JOIN table1 t2
ON t1.Person = t2.Person
and t2.Day = 2
LEFT JOIN table1 t3
ON t1.Person = t3.Person
and t3.Day = 3
LEFT JOIN table1 t4
ON t1.Person = t4.Person
and t4.Day = 4
WHERE
t1.Day = 1
ORDER BY
t1.Person
另一种方法是使用MAX(CASE),但我不喜欢这样使用聚合
Select
t1.Person,
COALESCE(MAX(CASE WHEN t1.Day = 1 then t1.Job END), 'N/A') [1],
COALESCE(MAX(CASE WHEN t1.Day = 2 then t1.Job END), 'N/A') [2],
COALESCE(MAX(CASE WHEN t1.Day = 3 then t1.Job END), 'N/A') [3],
COALESCE(MAX(CASE WHEN t1.Day = 4 then t1.Job END), 'N/A') [4]
FROM
table1 t1
GROUP BY
t1.Person
最后是pivot子句,我不太喜欢,因为这里的MAX
SELECT person,
COALESCE([1], 'N/A') [1],
COALESCE([2], 'N/A') [2],
COALESCE([3], 'N/A') [3],
COALESCE([4], 'N/A') [4]
FROM (SELECT t1.person,
t1.day,
t1.job
FROM table1 t1) p
PIVOT (Max (job)
FOR day IN ( [1],
[2],
[3],
[4]) ) AS pvt
如果需要对任意数量的列执行此操作,也可以使用动态SQL执行此操作:
create procedure [dbo].[MyStoredProcedure]
as
begin
declare @stmt nvarchar(max)
select @stmt =
isnull(@stmt + ', ', '') +
'isnull(max(case when [Day] = ' + cast([Day] as nvarchar(max)) +
' then Job end), ''N/A'') as [' + cast([Day] as nvarchar(max)) + ']'
from (select distinct [Day] from Table1) as t
order by [Day]
select @stmt = '
select
Person, ' + @stmt +'
from Table1
group by Person'
exec sp_executesql
@stmt = @stmt
end
如果需要对任意数量的列执行此操作,也可以使用动态SQL执行此操作:
create procedure [dbo].[MyStoredProcedure]
as
begin
declare @stmt nvarchar(max)
select @stmt =
isnull(@stmt + ', ', '') +
'isnull(max(case when [Day] = ' + cast([Day] as nvarchar(max)) +
' then Job end), ''N/A'') as [' + cast([Day] as nvarchar(max)) + ']'
from (select distinct [Day] from Table1) as t
order by [Day]
select @stmt = '
select
Person, ' + @stmt +'
from Table1
group by Person'
exec sp_executesql
@stmt = @stmt
end
谢谢!不过,我的日子(专栏)您的动态解决方案可以运行吗?@RG-3您忘记执行语句-
exec sp_executesql@stmt=@stmt
,但是,当我通过C#调用此存储过程时,我不想将任何内容作为参数输入:\n您不必输入参数。只需创建不带参数的过程并在其中写入整个语句即可it@RomanP请看我在问题中的编辑。你会得到要点的。谢谢!不过,我的日子(专栏)您的动态解决方案可以运行吗?@RG-3您忘记执行语句-exec sp_executesql@stmt=@stmt
,但是,当我通过C#调用此存储过程时,我不想将任何内容作为参数输入:\n您不必输入参数。只需创建不带参数的过程并在其中写入整个语句即可it@RomanPekar:请看我在问题中的编辑。您将了解要点。我的天数(列)最多63或更多…如果我这样做,将需要大量的代码行。@RG-3您可以很容易地生成SQL语句。它是否在上的运行时生成不应基于您的要求。我的天数(列)最多63行或更多…如果我继续这样做,将需要很多行代码。@RG-3您可以非常轻松地生成SQL语句。它是否在运行时生成取决于您的要求。