将行名转换为列名,并按日期求和并显示数据

Posted

技术标签:

【中文标题】将行名转换为列名,并按日期求和并显示数据【英文标题】:Transform row name into column name and also sum & show the data datewise 【发布时间】:2020-12-15 06:58:53 【问题描述】:

我想为以下问题写一个查询。

我想

例子:

NAME Start Date Time End Date time
Noida 06-03-2020 06:30 06-03-2020 07:30
Noida 07-03-2020 08:54 07-03-2020 09:45
Noida 06-03-2020 03:30 06-03-2020 05:30
Noida 08-03-2020 04:55 08-03-2020 06:30
Delhi 08-03-2020 04:40 08-03-2020 05:30
Delhi 14-03-2020 04:40 14-03-2020 05:30

现在我们要做的是: 返回日期数据,然后对该日期的总时间求和,即名称明智,行“名称”转换为列名称,如果任何日期的数据不可用,则写入“无数据”。

预期结果将是:

Date_Wise Noida_total_ Time Delhi_total_ Time
06-03-2020 03:00:00 No data
07-03-2020 00:51:00 No data
08-03-2020 01:35:00 00:50:00
14-03-2020 No data 00:50:00

• 第一行:日期为 2020 年 3 月 3 日,然后是诺伊达总时间的总和,然后德里没有 2020 年 6 月 3 日的任何数据,因此我们写为“无数据”。

同样适用于所有行。

【问题讨论】:

如果一个条目跨越一天以上怎么办?例如,开始日期为2020-03-06 09:00,结束日期为2020-03-07 05:00? 然后根据开始日期将其包含在内。就像在您的示例中,它们之间的总时间为 20 小时,日期为 2020-03-06 。 【参考方案1】:

我们可以在这里使用日历表方法:

SELECT
    SUM(CASE WHEN t.NAME = 'Noida' 
             THEN DATEDIFF(hour, [Start Date Time], [End Date Time]) ELSE 0
        END) AS Noida_total_Time,
    SUM(CASE WHEN t.NAME = 'Delhi' 
             THEN DATEDIFF(hour, [Start Date Time], [End Date Time]) ELSE 0
        END) AS Delhi_total_Time
FROM (SELECT DISTINCT CAST([Start Date Time] AS date) AS Date_Wise FROM yourTable) d
LEFT JOIN yourTable t
    ON d.Date_Wise = CAST(t.[Start Date Time] AS date)
GROUP BY
    d.Date_Wise
ORDER BY
    d.Date_Wise;

【讨论】:

难道不是SUM 而不是MAX 吗?看起来 OP 想要每天的总小时数。 @Zack 我同意你的评论并编辑了我的答案。【参考方案2】:

给你:


declare
    @t table ([NAME] varchar (100), [Start Date Time] datetime, [End DAte time] datetime)   

declare
    @t2 table (rn int, dates date)

declare
    @t_res table (Date_Wise date, [Noida_total_ Time] varchar (100), [Delhi_total_ Time] varchar (100))

declare
    @i int=1, @d date

insert @t  
select 'Noida', convert(datetime, '06-03-2020 06:30', 105), convert(datetime, '06-03-2020 07:30' , 105)
union all
select 'Noida', convert(datetime, '07-03-2020 08:54' , 105),    convert(datetime, '07-03-2020 09:45' , 105)
union all
select 'Noida', convert(datetime, '06-03-2020 03:30' , 105),    convert(datetime, '06-03-2020 05:30' , 105)
union all
select 'Noida', convert(datetime, '08-03-2020 04:55' , 105),    convert(datetime, '08-03-2020 06:30' , 105)
union all
select 'Delhi', convert(datetime, '08-03-2020 04:40' , 105),    convert(datetime, '08-03-2020 05:30' , 105)
union all
select 'Delhi', convert(datetime, '14-03-2020 04:40' , 105),    convert(datetime, '14-03-2020 05:30' , 105)

insert into @t2
select ROW_NUMBER() over (order by (select dates)), dates from (
    select distinct cast([Start Date Time] as date) dates from @t
    union
    select distinct cast([End DAte time] as date) from @t
    )t

declare
    @dur_n time
    ,@dur_d time
    

while @i<=(select max(rn) from @t2 )
begin
    select @d=dates from @t2 where rn=@i

    select @dur_n=CONVERT(varchar, DATEADD(ms, datediff(ss, min(t), max(t)) * 1000, 0), 114)
    from (
        select [Start Date Time] t from @t where cast([Start Date Time] as date) =@d and [NAME]='Noida'
        union all
        select [End DAte time] t from @t where cast([End DAte time]  as date) =@d and [NAME]='Noida'
    )t1


    select @dur_d=CONVERT(varchar, DATEADD(ms, datediff(ss, min(t), max(t)) * 1000, 0), 114)
    from (
        select [Start Date Time] t from @t where cast([Start Date Time] as date) =@d and [NAME]='Delhi'
        union all
        select [End DAte time] t from @t where cast([End DAte time]  as date) =@d and [NAME]='Delhi'
    )t1


    set @i=@i+1

    insert into @t_res
    select @d, isnull(cast(@dur_n as varchar(100)), 'No data'), isnull(cast(@dur_d as varchar(100)), 'No data')
end

select * from  @t_res


【讨论】:

谁提出了不喜欢,你能分享一下什么不是正确的解决方案吗?

以上是关于将行名转换为列名,并按日期求和并显示数据的主要内容,如果未能解决你的问题,请参考以下文章

将行值转换为列名

如何动态地将行转换为列,并为每列使用不同的列名

如何根据日期列将行转换为列?

SQL Server - Pivot 将行转换为列(带有额外的行数据)

将行转换为涉及日期的列

怎么从文本中匹配日期格式并按此排序(Java)