使用SQL查询分组并展开到新列?

使用SQL查询分组并展开到新列?,sql,sql-server,tsql,group-by,Sql,Sql Server,Tsql,Group By,拥有这些数据: 名称 日期 约翰 2021-03-01 10:00 保罗 2021-03-01 11:00 保罗 2021-03-01 14:20 约翰 2021-03-01 15:00 保罗 2021-03-01 17:00 基于Larnu的帮助,这起到了作用: WITH RNs AS( SELECT [Name], [DateTime], ROW_NUMBER() OVER (PARTITION BY Name ORDER B

拥有这些数据:

名称 日期 约翰 2021-03-01 10:00 保罗 2021-03-01 11:00 保罗 2021-03-01 14:20 约翰 2021-03-01 15:00 保罗 2021-03-01 17:00
基于Larnu的帮助,这起到了作用:

  WITH RNs AS(
    SELECT       [Name],
          [DateTime],
           ROW_NUMBER() OVER (PARTITION BY Name ORDER BY (SELECT NULL)) AS RN
    FROM dbo.Punch
    WHERE Date = '2016-04-18'
    )
SELECT Name,
    
       MAX(CASE RN WHEN 1 THEN [DateTime] END) AS Result1,
       MAX(CASE RN WHEN 2 THEN [DateTime] END) AS Result2,
       MAX(CASE RN WHEN 3 THEN [DateTime] END) AS Result3,
       MAX(CASE RN WHEN 4 THEN [DateTime] END) AS Result4

FROM RNs R
GROUP BY Name

基于Larnu的帮助,这起到了作用:

  WITH RNs AS(
    SELECT       [Name],
          [DateTime],
           ROW_NUMBER() OVER (PARTITION BY Name ORDER BY (SELECT NULL)) AS RN
    FROM dbo.Punch
    WHERE Date = '2016-04-18'
    )
SELECT Name,
    
       MAX(CASE RN WHEN 1 THEN [DateTime] END) AS Result1,
       MAX(CASE RN WHEN 2 THEN [DateTime] END) AS Result2,
       MAX(CASE RN WHEN 3 THEN [DateTime] END) AS Result3,
       MAX(CASE RN WHEN 4 THEN [DateTime] END) AS Result4

FROM RNs R
GROUP BY Name

如果您想使查询动态化,这意味着无论您对任何给定名称有多少个日期,此查询都将自动生成相应数量的列,请尝试以下查询:

模式:

 create table mytable (Name     varchar(50),[Date] Datetime);
 
 insert into mytable values('John' , '2021-03-01 10:00');
 insert into mytable values('Paul' , '2021-03-01 11:00');
 insert into mytable values('Paul' , '2021-03-01 14:20');
 insert into mytable values('John' , '2021-03-01 15:00');
 insert into mytable values('Paul' , '2021-03-01 17:00');
查询:

 declare @cols  as varchar(max), @colsForSelect as varchar(max), @query as varchar(max);
 
 select @colsForSelect=string_agg(concat(quotename(rn),' ', datename),',' )from(
 select distinct concat('Date',rn) datename,rn from
 (SELECT row_number()over(partition by name order by [date])rn from mytable)t)a
 
 select @cols =string_agg(quotename(rn),',') from (
 select distinct rn from
 (SELECT row_number()over(partition by name order by [date])rn from mytable)t)a
 
 set @query = 'Select Name, ' + @colsForSelect + ' from 
             (
                SELECT *,row_number()over(partition by name order by [date])rn 
                from mytable
             ) x
             pivot 
             (
                 max([date])
                 for rn in (' + @cols + ')
             ) p 
             group by Name,' + @cols 
  
 execute(@query);
输出:

名称 日期1 日期2 日期3 约翰 2021-03-01 10:00:00.000 2021-03-01 15:00:00.000 无效的 保罗 2021-03-01 11:00:00.000 2021-03-01 14:20:00.000 2021-03-01 17:00:00.000
如果您想使查询动态化,这意味着无论您对任何给定名称有多少个日期,此查询都将自动生成相应数量的列,请尝试以下查询:

模式:

 create table mytable (Name     varchar(50),[Date] Datetime);
 
 insert into mytable values('John' , '2021-03-01 10:00');
 insert into mytable values('Paul' , '2021-03-01 11:00');
 insert into mytable values('Paul' , '2021-03-01 14:20');
 insert into mytable values('John' , '2021-03-01 15:00');
 insert into mytable values('Paul' , '2021-03-01 17:00');
查询:

 declare @cols  as varchar(max), @colsForSelect as varchar(max), @query as varchar(max);
 
 select @colsForSelect=string_agg(concat(quotename(rn),' ', datename),',' )from(
 select distinct concat('Date',rn) datename,rn from
 (SELECT row_number()over(partition by name order by [date])rn from mytable)t)a
 
 select @cols =string_agg(quotename(rn),',') from (
 select distinct rn from
 (SELECT row_number()over(partition by name order by [date])rn from mytable)t)a
 
 set @query = 'Select Name, ' + @colsForSelect + ' from 
             (
                SELECT *,row_number()over(partition by name order by [date])rn 
                from mytable
             ) x
             pivot 
             (
                 max([date])
                 for rn in (' + @cols + ')
             ) p 
             group by Name,' + @cols 
  
 execute(@query);
输出:

名称 日期1 日期2 日期3 约翰 2021-03-01 10:00:00.000 2021-03-01 15:00:00.000 无效的 保罗 2021-03-01 11:00:00.000 2021-03-01 14:20:00.000 2021-03-01 17:00:00.000
我尝试了Stuff函数,而不是2017年服务器上引入的sting_agg。如果您使用的是2017年以下版本,则可以使用以下查询

declare @column_name varchar(5000)
declare @col_name varchar(5000)

set @column_name = (select stuff((select  ','+'['+cast(rn as varchar(1000))+']' from(select distinct row_number()over(partition by name order by (select null))as rn from mytable)a
for xml path('')), 1,1,''))

set @col_name = (select stuff((select  ','+'['+cast(rn as varchar(1000))+']' +' Date'+cast(rn as varchar(1000)) from(select distinct row_number()over(partition by name order by (select null))as rn from mytable)a
for xml path('')), 1,1,'')) 

exec('select name, '+@col_name +'
from (
select  row_number()over(partition by name order by (select null))rn, year([date]) yr, *
from mytable
)a
pivot
(
max([date]) for  [rn]  in ('+@column_name+' )
)pv')

我尝试了Stuff函数,而不是2017年服务器上引入的sting_agg。如果您使用的是2017年以下版本,则可以使用以下查询

declare @column_name varchar(5000)
declare @col_name varchar(5000)

set @column_name = (select stuff((select  ','+'['+cast(rn as varchar(1000))+']' from(select distinct row_number()over(partition by name order by (select null))as rn from mytable)a
for xml path('')), 1,1,''))

set @col_name = (select stuff((select  ','+'['+cast(rn as varchar(1000))+']' +' Date'+cast(rn as varchar(1000)) from(select distinct row_number()over(partition by name order by (select null))as rn from mytable)a
for xml path('')), 1,1,'')) 

exec('select name, '+@col_name +'
from (
select  row_number()over(partition by name order by (select null))rn, year([date]) yr, *
from mytable
)a
pivot
(
max([date]) for  [rn]  in ('+@column_name+' )
)pv')

这回答了你的问题吗?如果没有,为什么不呢?可能吧。我搜索了一下,但没有找到那个问题/答案。谢谢。您使用的是哪个版本的sql server?我已经安装了sql server 2014和2017。这是否回答了您的问题?如果没有,为什么不呢?可能吧。我搜索了一下,但没有找到那个问题/答案。谢谢。您使用的是哪一版本的sql server?我已经安装了sql server 2014和2017,运行良好。祝你一切顺利。最好的祝愿。这也很有用。谢谢,非常欢迎。但如果日期的数目是固定的,那么您的查询将比这个查询运行得快得多。谢谢您的提问。这是一个很好的例子。最好的祝愿。这也很有用。谢谢,非常欢迎。但如果日期的数目是固定的,那么您的查询将比这个查询运行得快得多。谢谢您的提问。这是一个很好的例子。最美好的祝福。