Sql 按班次分组时间戳

Sql 按班次分组时间戳,sql,tsql,datetime,Sql,Tsql,Datetime,在我们工厂,我们有以下班次: 1:Mo-周五:上午5点-下午1点 2:Mo-周五:下午1:00-9:00 3:Mo-Fri:9pm-5am 4a:星期六:上午5时至下午5时 4b:周日:下午5点-周一上午5点 在某个表中,我们有几个日期时间项,我想使用查询对它们进行分组。对于班次1、2和3,此查询工作正常: CASE WHEN DATEPART(hh, c.date_time_stamp) >= 5 AND DATEPART(hh, c.date_time_stamp) <

在我们工厂,我们有以下班次:

  • 1:Mo-周五:上午5点-下午1点
  • 2:Mo-周五:下午1:00-9:00
  • 3:Mo-Fri:9pm-5am
  • 4a:星期六:上午5时至下午5时
  • 4b:周日:下午5点-周一上午5点
在某个表中,我们有几个日期时间项,我想使用查询对它们进行分组。对于班次1、2和3,此查询工作正常:

  CASE
WHEN DATEPART(hh, c.date_time_stamp) >= 5 AND DATEPART(hh, c.date_time_stamp) < 13 THEN CONVERT(VARCHAR(10), c.date_time_stamp, 103) + ' shift 1'
WHEN DATEPART(hh, c.date_time_stamp) >= 13 AND DATEPART(hh, c.date_time_stamp) < 21 THEN CONVERT(VARCHAR(10), c.date_time_stamp, 103) + ' shift 2'
WHEN DATEPART(hh, c.date_time_stamp) >= 21 AND DATEPART(hh, c.date_time_stamp) < 24 THEN CONVERT(VARCHAR(10), c.date_time_stamp, 103) + ' shift 3'
WHEN DATEPART(hh, c.date_time_stamp) >= 00 AND DATEPART(hh, c.date_time_stamp) < 5 THEN CONVERT(VARCHAR(10), DATEADD(DAY, -1, c.date_time_stamp), 103)  + ' shift 3'  END AS shift,

这将为您提供轮班服务。它的工作原理是认识到这是一个数学问题,而不是数据库问题

每周有21个班次,我们创建一个表变量来保存班次名称-您可能希望为此创建一个永久表,在数字列上有一个索引

通过在时间和日期时间之间按小时获取
DATEDIFF
,该时间和日期时间设置为我们感兴趣的任何日期之前的星期一的5:00,并取其模24*7(一周的小时数),我们得到一个数字,指示星期一超过5:00的时间(即0班)。把这个除以8,你就得到了班次号

DECLARE @FirstEverShift datetime = CONVERT(datetime, '2011-12-26 05:00')

DECLARE @ShiftTypes TABLE
(Number int NOT NULL PRIMARY KEY,
 Shift  nvarchar(2) NOT NULL)

INSERT @ShiftTypes
VALUES
(0, '1'),
(1, '2'),
(2, '3'),
(3, '1'),
(4, '2'),
(5, '3'),
(6, '1'),
(7, '2'),
(8, '3'),
(9, '1'),
(10, '2'),
(11, '3'),
(12, '1'),
(13, '2'),
(14, '3'),
(15, '4a'),
(16, 'NA'),
(17, 'NA'),
(18, '4b'),
(19, 'NA'),
(20, 'NA')

SELECT  s.date_time_stamp
        ,st.Shift
FROM    shifts s
        INNER JOIN
        @ShiftTypes st ON st.Number=DATEDIFF(HOUR, @FirstEverShift, s.date_time_stamp) % (24*7) / 8
编辑

我意识到周末轮班是12小时而不是8小时。这种方法很有效,但需要修改,我不打算这样做,因为我在平板电脑上


不是除以8,而是除以4,这意味着表格变量必须从0到40,每8小时轮班需要2个数字,每12小时需要3个数字。

如果您担心性能,为移位ID添加一个额外的列。可以作为具有持久值的计算列,也可以使用在插入/更新时计算移位ID的触发器。在上面放一个索引,完成。谢谢你的评论,我之前已经考虑过了,但它是一个外部数据库的表(它不是我们的,它是WMS系统的数据库)…@KoenVC根据上面的示例数据,如果你运行假定的函数,你的预期结果是什么?那么你至少应该使用
在。。。和
以允许使用索引(如果存在)。使用
DATEPART
会导致表格扫描,速度较慢。但是,如果
日期时间戳上不存在索引,那就没关系了,反正会有一个表扫描。@KoenVC你能为我们提供某个表中
的样本数据吗
?嗨,戴尔,我来试试!
DECLARE @FirstEverShift datetime = CONVERT(datetime, '2011-12-26 05:00')

DECLARE @ShiftTypes TABLE
(Number int NOT NULL PRIMARY KEY,
 Shift  nvarchar(2) NOT NULL)

INSERT @ShiftTypes
VALUES
(0, '1'),
(1, '2'),
(2, '3'),
(3, '1'),
(4, '2'),
(5, '3'),
(6, '1'),
(7, '2'),
(8, '3'),
(9, '1'),
(10, '2'),
(11, '3'),
(12, '1'),
(13, '2'),
(14, '3'),
(15, '4a'),
(16, 'NA'),
(17, 'NA'),
(18, '4b'),
(19, 'NA'),
(20, 'NA')

SELECT  s.date_time_stamp
        ,st.Shift
FROM    shifts s
        INNER JOIN
        @ShiftTypes st ON st.Number=DATEDIFF(HOUR, @FirstEverShift, s.date_time_stamp) % (24*7) / 8