使用 SQL 查询对新列进行分组和扩展?

Posted

技术标签:

【中文标题】使用 SQL 查询对新列进行分组和扩展?【英文标题】:Group and expand to new columns using a SQL query? 【发布时间】:2021-06-25 07:38:41 【问题描述】:

拥有这些数据:

Name Date
John 2021-03-01 10:00
Paul 2021-03-01 11:00
Paul 2021-03-01 14:20
John 2021-03-01 15:00
Paul 2021-03-01 17:00

如何获得此结果(按 ASC 排序的日期)

Name Date1 Date2 Date2
John 2021-03-01 10:00 2021-03-01 15:00 NULL
Paul 2021-03-01 11:00 2021-03-01 14:20 2021-03-01 17:00

谢谢。

【问题讨论】:

这能回答你的问题吗? Group by column and multiple Rows into One Row multiple columns如果没有,为什么不呢? 可能。我搜索但没有找到那个问题/答案。谢谢。 你使用的是哪个版本的sql server? 我安装了 SQL Server 2014 和 2017 【参考方案1】:

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

架构:

 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);

输出:

Name Date1 Date2 Date3
John 2021-03-01 10:00:00.000 2021-03-01 15:00:00.000 null
Paul 2021-03-01 11:00:00.000 2021-03-01 14:20:00.000 2021-03-01 17:00:00.000

db小提琴here

【讨论】:

这也很有用。谢谢 不客气。但是,如果日期数是固定的,那么您的查询将比这个运行得快得多。 感谢您的提问。这是一个不错的。最良好的祝愿。【参考方案2】:

在 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

【讨论】:

【参考方案3】:

我尝试过使用 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 查询对新列进行分组和扩展?的主要内容,如果未能解决你的问题,请参考以下文章

SQL关联查询 直接join 和子查询的区别

sql分组查询和连接查询

sql server——分组查询(方法和思想)

电源查询 - 扩展新列

THINKPHP中怎么对数据进行分组查询?

SQL查询语句.GroupBy分组