使用sqlserver根据时间段获取不同的MO

Posted

技术标签:

【中文标题】使用sqlserver根据时间段获取不同的MO【英文标题】:Use sqlserver to get different MO according to time period 【发布时间】:2020-09-19 12:49:31 【问题描述】:

源表route

CREATE TABLE [dbo].route(
    [sfcno] varchar(20) NOT NULL,
    [time] [datetime]NOT NULL
) ON [PRIMARY]
GO

insert into route(sfcno ,time)
values (10,'08:00'),
       (10,'08:10'),
       (11,'08:30'),
       (22,'09:10'),
       (33,'10:10'),
       (44,'11:10'),
       (555,'11:30')

我想得到以下内容

08:00-09:00   09:00-10:00   10:00-11:00   11:00-12:00
10,11         22            33            44,555

【问题讨论】:

【参考方案1】:

我发现将结果放在行中比放在列中更有意义:

select 
    format(datepart(hour, time), '00') + ':00-' 
        +  format(datepart(hour, time) + 1, '00') + ':00' as timeslot, 
    string_agg(sfcno, ',') within group(order by sfcno) sfcnos
from route 
group by datepart(hour, time)
时隙 | sfcnos :------------ | :-------- 08:00-09:00 | 10,10,11 09:00-10:00 | 22 10:00-11:00 | 33 11:00-12:00 | 44,555

如果你真的想要列,那么你需要条件聚合 - 输入时间会更长:

select 
    string_agg(case when datepart(hour, time) =  8 then sfcno end, ',') within group(order by sfcno) as time_slot_08_09,
    string_agg(case when datepart(hour, time) =  9 then sfcno end, ',') within group(order by sfcno) as time_slot_09_10,
    string_agg(case when datepart(hour, time) = 10 then sfcno end, ',') within group(order by sfcno) as time_slot_10_11,
    string_agg(case when datepart(hour, time) = 11 then sfcno end, ',') within group(order by sfcno) as time_slot_11_12
from route 
time_slot_08_09 | time_slot_09_10 | time_slot_10_11 | time_slot_11_12 :---------------- | :---------------- | :---------------- | :-------------- 10,10,11 | 22 | 33 | 44,555

Demo on DB Fiddle

【讨论】:

谢谢,但我需要不同的 sfcno。如果你有更好的答案,你能告诉我吗?【参考方案2】:

您想要得到的是由于定义的规则而将行转换为列的旋转。更喜欢使用动态旋转,如下图所示:

DECLARE @cols  AS NVARCHAR(MAX),  @query AS NVARCHAR(MAX)

SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(
                                   CONCAT(
                                          FORMAT(DATEPART(hour, time), '00') + ':00',
                                          '-',
                                          FORMAT(DATEPART(hour, time) + 1, '00') + ':00'
                                          )
                                   ) AS time
                        FROM route
                     
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


SET  @query = 
 N'SELECT '+ @cols + N' 
     FROM
     (
      SELECT STRING_AGG(sfcno, '','') WITHIN GROUP (ORDER BY sfcno) AS sfcno, time
        FROM ( SELECT DISTINCT sfcno,  
                      CONCAT(
                             FORMAT(DATEPART(hour, time), ''00'') + '':00-'',
                             FORMAT(DATEPART(hour, time) + 1, ''00'') + '':00''
                             ) AS time
                 FROM route ) r
       GROUP BY time 
      ) q
    PIVOT 
    (
     MAX(sfcno) FOR time IN (' + @cols + N')
    ) p '

EXEC sp_executesql @query;

Demo

【讨论】:

不好意思,我的sqlserver版本是2012

以上是关于使用sqlserver根据时间段获取不同的MO的主要内容,如果未能解决你的问题,请参考以下文章

sqlserver如何根据当前日期获得上月某一天的日期

mysql怎根据时间获取是星期几

mysql怎根据时间获取是星期几

我需要根据 SQL Server 2008 中的以下详细信息获取结果

sql获取当前周几

在SqlServer2000中怎么确定时间的类型