如何按小时或 10 分钟对时间进行分组?

发布于 2024-10-17 11:16:53 字数 460 浏览 3 评论 0原文

就像我做的那样

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date]

我怎样才能指定小组时间?我正在使用 MS SQL 2008。

我已经尝试过使用 % 10/ 10

SELECT MIN([Date]) AS RecT, AVG(Value)
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY (DATEPART(MINUTE, [Date]) / 10)
  ORDER BY RecT

是否可以使日期输出没有毫秒?

Like when I do

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date]

How can I specify the group period? I'm using MS SQL 2008.

I've tried this, both with % 10 and / 10.

SELECT MIN([Date]) AS RecT, AVG(Value)
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY (DATEPART(MINUTE, [Date]) / 10)
  ORDER BY RecT

Is it possible to make Date output without milliseconds?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

余罪 2024-10-24 11:16:53

终于完成了

GROUP BY
DATEPART(YEAR, DT.[Date]),
DATEPART(MONTH, DT.[Date]),
DATEPART(DAY, DT.[Date]),
DATEPART(HOUR, DT.[Date]),
(DATEPART(MINUTE, DT.[Date]) / 10)

finally done with

GROUP BY
DATEPART(YEAR, DT.[Date]),
DATEPART(MONTH, DT.[Date]),
DATEPART(DAY, DT.[Date]),
DATEPART(HOUR, DT.[Date]),
(DATEPART(MINUTE, DT.[Date]) / 10)
冰火雁神 2024-10-24 11:16:53

简短而温馨

GROUP BY DATEDIFF(MINUTE, '2000', date_column) / 10

,对 Derek 的回答表示衷心的感谢,它1构成了本文的核心。 如果您使用的是 SQL Server 2022+,请直接访问Martin 的回答

实际使用

SELECT   DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
                                                             AS [date_truncated],
         COUNT(*) AS [records_in_interval],
         AVG(aa.[value]) AS [average_value]
FROM     [friib].[dbo].[archive_analog] AS aa
-- WHERE aa.[date] > '1900-01-01'
GROUP BY DATEDIFF(MINUTE, '2000', aa.[date]) / 10
-- HAVING SUM(aa.[value]) > 1000
ORDER BY [date_truncated]

详细信息和额外注释

Bin 间隔大小

MINUTE10 术语可以更改为任何DATEPART 和整数,2< /sup> 分别分组为不同的时间间隔。例如,10MINUTE 表示十分钟间隔; 6HOUR 是六个小时的间隔。

如果您多次更改间隔,则将其声明为变量可能会受益。

DECLARE @interval int = 10;

SELECT   DATEADD(MINUTE, DATEDIFF(…) / @interval * @interval, '2000')
…
GROUP BY                 DATEDIFF(…) / @interval

值类型

分组的实际值是一组距 2000-01-01 00:00 的相对偏移量。这意味着长时间间隔的数据源是可以的。其他一些答案在年份之间存在冲突。

GROUP BY 表达式乘以间隔大小并将其包装在 DATEADD 调用中将返回一个 DATETIME 值。 将其包含在 SELECT 语句中将为您的输出提供带有截断时间戳的单列。请参阅上面的“实际用法”示例。

移动 bin 间隔的标签

DATEDIFF 之后的除法 (/) 运算将值截断为整数(FLOOR 快捷方式),从而产生 < SELECT 输出中每行的时间间隔的开始时间。

如果您想用其间隔的中间结束来标记每一行,您可以使用以下命令调整DATEADD第二项中的划分下表中粗体部分:

标记为查询修改Credit to
End…) / 10 * 10 + 10 , '2000' )丹尼尔·埃尔金顿
…) / 10 * 10 + (10 / 2.0) , '2000')

如果您想向内舍入间隔,使每个时间戳代表其之前的一半间隔和之后的一半间隔,请使用类似以下内容:

DATEADD(MINUTE, ROUND(1. * DATEDIFF(MINUTE, '2000', date_column) / 10, 0) * 10, '2000')

注意 1. 来执行未截断的操作部门代替。您需要修改 GROUP BY 以进行匹配,并且您可能需要使用整个 ROUND(…) 表达式以避免任何意外的浮点舍入。

日期数学小知识

'2000' 是一个“锚定日期”,SQL 将围绕该日期执行日期数学。大多数示例代码使用 0 作为锚点,但是 JereonH 发现您在以下情况下遇到整数溢出:按秒或毫秒对最近的日期进行分组。3

如果您的数据跨越几个世纪,4GROUP BY中使用单个锚定日期来表示秒否则毫秒仍然会遇到溢出。对于这些查询,您可以要求每一行将分箱比较锚定到其自己日期的午夜。

使用这两个替换之一来代替查询中出现的 '2000'

  • DATEADD(DAY, DATEDIFF(DAY, 0, aa.[date]), 0)
  • CONVERT(DATETIME, CONVERT(DATE, aa.[date]))

您的查询将完全不可读,但它会起作用。


1 在发布几年后我意识到我的代码可以简化为几乎德里克的回答
2 如果您希望所有 :00 时间戳都符合分箱条件,请使用您的 DATEPART 的最大值可以均匀划分为。5 作为反例,将结果分组为 13 分钟或 37 小时的 bin 将跳过一些 :00,但是 它应该仍然可以正常工作
3 数学表示 232 ≈ 4.29E+9。这意味着对于 SECONDDATEPART,两边各有 43 亿秒,相当于“锚定日期 ± 136 年”。同样,232 毫秒约为 49.7 天。
4 如果您的数据实际上跨越了几个世纪或几千年,并且仍然精确到秒或毫秒......恭喜!无论你在做什么,继续做下去。
5 如果您想知道为什么我们的时钟顶部有一个 12,请思考5是6(12的一半)或以下的唯一整数不是 12 的因数。然后请注意 5 × 12 = 60。对于包含小时、分钟和秒的 bin 大小,您有很多选择。

Short and sweet

GROUP BY DATEDIFF(MINUTE, '2000', date_column) / 10

With heavy acknowledgements to Derek's answer, which1 forms the core of this one. If you're on SQL Server 2022+, go straight to Martin's answer.

Practical usage

SELECT   DATEADD(MINUTE, DATEDIFF(MINUTE, '2000', aa.[date]) / 10 * 10, '2000')
                                                             AS [date_truncated],
         COUNT(*) AS [records_in_interval],
         AVG(aa.[value]) AS [average_value]
FROM     [friib].[dbo].[archive_analog] AS aa
-- WHERE aa.[date] > '1900-01-01'
GROUP BY DATEDIFF(MINUTE, '2000', aa.[date]) / 10
-- HAVING SUM(aa.[value]) > 1000
ORDER BY [date_truncated]

Details and extra commentary

Bin interval size

The MINUTE and 10 terms can be changed to any DATEPART and integer,2 respectively, to group into different time intervals. For example, 10 with MINUTE is ten minute intervals; 6 with HOUR is six hour intervals.

If you change the interval a lot, you might benefit from declaring it as a variable.

DECLARE @interval int = 10;

SELECT   DATEADD(MINUTE, DATEDIFF(…) / @interval * @interval, '2000')
…
GROUP BY                 DATEDIFF(…) / @interval

Value type

The actual values being grouped are a set of relative offsets from 2000-01-01 00:00. This means data sources over long time intervals are fine. Some other answers have collision between years.

Multiplying the GROUP BY expression by the interval size and wrapping it in a DATEADD invocation will return you a DATETIME value. Including it in the SELECT statement will give your output a single column with the truncated timestamp. See the "Practical Usage" example above.

Shifting the label for the bin interval

The division (/) operation after DATEDIFF truncates values to integers (a FLOOR shortcut), which yields the beginning of time intervals for each row in your SELECT output.

If you want to label each row with the middle or end of its interval, you can tweak the division in the second term of DATEADD with the bold part in the table below:

Labeled asQuery modificationCredit to
End…) / 10 * 10 + 10 , '2000')Daniel Elkington
Middle…) / 10 * 10 + (10 / 2.0) , '2000')

If you want to round your intervals inward such that each timestamp represents half an interval before and half an interval after it, use something like this:

DATEADD(MINUTE, ROUND(1. * DATEDIFF(MINUTE, '2000', date_column) / 10, 0) * 10, '2000')

Note the 1. to do untruncated division instead. You will need to modify your GROUP BY to match, and you may want to use the whole ROUND(…) expression to avoid any unexpected float rounding.

Date math trivia

'2000' is an "anchor date" around which SQL will perform the date math. Most sample code uses 0 for the anchor, but JereonH discovered that you encounter an integer overflow when grouping more-recent dates by seconds or milliseconds.3

If your data spans centuries,4 using a single anchor date in the GROUP BY for seconds or milliseconds will still encounter the overflow. For those queries, you can ask each row to anchor the binning comparison to its own date's midnight.

Use one of the two replacements instead of '2000' wherever it appears in the query:

  • DATEADD(DAY, DATEDIFF(DAY, 0, aa.[date]), 0)
  • CONVERT(DATETIME, CONVERT(DATE, aa.[date]))

Your query will be totally unreadable, but it will work.


1 I realized several years after posting that my code could be simplified to nearly the same as Derek's answer.
2 If you want all :00 timestamps to be eligible for binning, use an integer that your DATEPART's maximum can evenly divide into.5 As a counterexample, grouping results into 13-minute or 37-hour bins will skip some :00s, but it should still work fine.
3 The math says 232 ≈ 4.29E+9. This means for a DATEPART of SECOND, you get 4.3 billion seconds on either side, which works out to "anchor date ± 136 years." Similarly, 232 milliseconds is ≈ 49.7 days.
4 If your data actually spans centuries or millenia and is still accurate to the second or millisecond… congratulations! Whatever you're doing, keep doing it.
5 If you ever wondered why our clocks have a 12 at the top, reflect on how 5 is the only integer from 6 (half of 12) or below that is not a factor of 12. Then note that 5 × 12 = 60. You have lots of choices for bin sizes with hours, minutes, and seconds.

二手情话 2024-10-24 11:16:53

在 T-SQL 中,您可以:

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date], DATEPART(hh, [Date])

或者

按分钟使用 DATEPART(mi, [Date])

按 10 分钟使用 DATEPART(mi, [Date]) / 10 (例如蒂莫西建议)

In T-SQL you can:

SELECT [Date]
  FROM [FRIIB].[dbo].[ArchiveAnalog]
  GROUP BY [Date], DATEPART(hh, [Date])

or

by minute use DATEPART(mi, [Date])

or

by 10 minutes use DATEPART(mi, [Date]) / 10 (like Timothy suggested)

司马昭之心 2024-10-24 11:16:53

对于 10 分钟的间隔,您可以

GROUP BY (DATEPART(MINUTE, [Date]) / 10)

像 tzup 和 Pieter888 已经提到的那样...进行一个小时的间隔,只需

GROUP BY DATEPART(HOUR, [Date])

For a 10 minute interval, you would

GROUP BY (DATEPART(MINUTE, [Date]) / 10)

As was already mentioned by tzup and Pieter888... to do an hour interval, just

GROUP BY DATEPART(HOUR, [Date])
枉心 2024-10-24 11:16:53

作者给出的原始答案效果很好。为了扩展这个想法,你可以做类似的事情

group by datediff(minute, 0, [Date])/10

,这样你就可以按比 60 分钟更长的时间段进行分组,比如 720,即半天等。

The original answer the author gave works pretty well. Just to extend this idea, you can do something like

group by datediff(minute, 0, [Date])/10

which will allow you to group by a longer period then 60 minutes, say 720, which is half a day etc.

笨死的猪 2024-10-24 11:16:53

应该是这样的

select timeslot, count(*)  
from 
    (
    select datepart('hh', date) timeslot
    FROM [FRIIB].[dbo].[ArchiveAnalog]  
    ) 
group by timeslot

(对语法不是 100% 确定 - 我更像是 Oracle 类型的人)

在 Oracle 中:

SELECT timeslot, COUNT(*) 
FROM
(  
    SELECT to_char(l_time, 'YYYY-MM-DD hh24') timeslot 
    FROM
    (
        SELECT l_time FROM mytab  
    )  
) GROUP BY timeslot 

Should be something like

select timeslot, count(*)  
from 
    (
    select datepart('hh', date) timeslot
    FROM [FRIIB].[dbo].[ArchiveAnalog]  
    ) 
group by timeslot

(Not 100% sure about the syntax - I'm more an Oracle kind of guy)

In Oracle:

SELECT timeslot, COUNT(*) 
FROM
(  
    SELECT to_char(l_time, 'YYYY-MM-DD hh24') timeslot 
    FROM
    (
        SELECT l_time FROM mytab  
    )  
) GROUP BY timeslot 
ゃ懵逼小萝莉 2024-10-24 11:16:53

对于 MySQL:

GROUP BY
DATE(`your_date_field`),
HOUR(`your_date_field`),
FLOOR( MINUTE(`your_date_field`) / 10);

For MySql:

GROUP BY
DATE(`your_date_field`),
HOUR(`your_date_field`),
FLOOR( MINUTE(`your_date_field`) / 10);
回眸一笑 2024-10-24 11:16:53

对于 SQL Server 2022+ 的用户,现在有一个专用的 DATE_BUCKET 函数可以满足此需求。

使用示例

DECLARE @ArchiveAnalog TABLE 
(
[Date] DATETIME2 PRIMARY KEY,
Value FLOAT
)

INSERT @ArchiveAnalog 
VALUES 
    ('2000-01-01 16:20:00.000', 1),  --Bucket 1
    ('2000-01-01 16:22:53.250', 2),
    ('2000-01-01 16:29:59.999', 3),
    ('2000-01-01 16:31:53.250', 4),  --Bucket 2
    ('2000-01-01 16:36:53.250', 5)


SELECT  
        DATE_BUCKET (minute, 10, [Date] ) AS BucketedValue,
        MIN([Date]) AS RecT, 
        COUNT(*) AS BucketCount,
        AVG(Value) AS BucketAvg
FROM @ArchiveAnalog
GROUP BY DATE_BUCKET (minute, 10, [Date] )
ORDER BY DATE_BUCKET (minute, 10, [Date] )
BucketedValueRecTBucketCountBucketAvg
2000-01-01 16:20:00.00000002000-01-01 16:20:00.000000032
2000-01-01 16:30:00.00000002000-01-01 16:31: 53.250000024.5

如果基础列已编入索引,则也可以是 相当高效

在此处输入图像描述

For people on SQL Server 2022+ there is now a dedicated DATE_BUCKET function that addresses this need.

Example usage

DECLARE @ArchiveAnalog TABLE 
(
[Date] DATETIME2 PRIMARY KEY,
Value FLOAT
)

INSERT @ArchiveAnalog 
VALUES 
    ('2000-01-01 16:20:00.000', 1),  --Bucket 1
    ('2000-01-01 16:22:53.250', 2),
    ('2000-01-01 16:29:59.999', 3),
    ('2000-01-01 16:31:53.250', 4),  --Bucket 2
    ('2000-01-01 16:36:53.250', 5)


SELECT  
        DATE_BUCKET (minute, 10, [Date] ) AS BucketedValue,
        MIN([Date]) AS RecT, 
        COUNT(*) AS BucketCount,
        AVG(Value) AS BucketAvg
FROM @ArchiveAnalog
GROUP BY DATE_BUCKET (minute, 10, [Date] )
ORDER BY DATE_BUCKET (minute, 10, [Date] )
BucketedValueRecTBucketCountBucketAvg
2000-01-01 16:20:00.00000002000-01-01 16:20:00.000000032
2000-01-01 16:30:00.00000002000-01-01 16:31:53.250000024.5

If the underlying column is indexed this can also be pretty efficient

enter image description here

月下客 2024-10-24 11:16:53

如果您想实际显示日期,请使用变量分组,并能够指定大于 60 分钟的时间范围:

DECLARE @minutes int
SET @minutes = 90

SELECT
    DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [Date]) / @minutes * @minutes, 0) as [Date],
    AVG([Value]) as [Value]
FROM [FRIIB].[dbo].[ArchiveAnalog]
GROUP BY
    DATEDIFF(MINUTE, 0, [Date]) / @minutes

If you want to actually display the date, have a variable grouping, and be able to specify larger time frames than 60 minutes:

DECLARE @minutes int
SET @minutes = 90

SELECT
    DATEADD(MINUTE, DATEDIFF(MINUTE, 0, [Date]) / @minutes * @minutes, 0) as [Date],
    AVG([Value]) as [Value]
FROM [FRIIB].[dbo].[ArchiveAnalog]
GROUP BY
    DATEDIFF(MINUTE, 0, [Date]) / @minutes
被翻牌 2024-10-24 11:16:53
declare @interval tinyint
set @interval = 30
select dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0), sum(Value_Transaction)
from Transactions
group by dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0)
declare @interval tinyint
set @interval = 30
select dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0), sum(Value_Transaction)
from Transactions
group by dateadd(minute,(datediff(minute,0,[DateInsert])/@interval)*@interval,0)
最美的太阳 2024-10-24 11:16:53

在 SQLite 中,为了按小时分组,您可以执行以下操作:

GROUP BY strftime('%H', [FRIIB].[dbo].[ArchiveAnalog].[Date]);

并按每 10 分钟分组:

GROUP BY strftime('%M', [FRIIB].[dbo].[ArchiveAnalog].[Date]) / 10;

In SQLite, in order to group by hour, you can do:

GROUP BY strftime('%H', [FRIIB].[dbo].[ArchiveAnalog].[Date]);

and to group by each 10 minutes:

GROUP BY strftime('%M', [FRIIB].[dbo].[ArchiveAnalog].[Date]) / 10;
昔日梦未散 2024-10-24 11:16:53

我的解决方案是使用函数创建一个包含日期间隔的表,然后将该表连接到我想要使用表中的日期间隔进行分组的数据。
然后在呈现数据时可以轻松选择日期间隔。

CREATE FUNCTION [dbo].[fn_MinuteIntervals]
    (
      @startDate SMALLDATETIME ,
      @endDate SMALLDATETIME ,
      @interval INT = 1
    )
RETURNS @returnDates TABLE
    (
      [date] SMALLDATETIME PRIMARY KEY NOT NULL
    )
AS
    BEGIN
        DECLARE @counter SMALLDATETIME
        SET @counter = @startDate
        WHILE @counter <= @endDate
            BEGIN
                INSERT INTO @returnDates VALUES ( @counter )
                SET @counter = DATEADD(n, @interval, @counter)
            END
        RETURN
    END

My solution is to use a function to create a table with the date intervals and then join this table to the data I want to group using the date interval in the table.
The date interval can then be easily selected when presenting the data.

CREATE FUNCTION [dbo].[fn_MinuteIntervals]
    (
      @startDate SMALLDATETIME ,
      @endDate SMALLDATETIME ,
      @interval INT = 1
    )
RETURNS @returnDates TABLE
    (
      [date] SMALLDATETIME PRIMARY KEY NOT NULL
    )
AS
    BEGIN
        DECLARE @counter SMALLDATETIME
        SET @counter = @startDate
        WHILE @counter <= @endDate
            BEGIN
                INSERT INTO @returnDates VALUES ( @counter )
                SET @counter = DATEADD(n, @interval, @counter)
            END
        RETURN
    END
坚持沉默 2024-10-24 11:16:53

对于 SQL Server 2012,虽然我相信它可以在 SQL Server 2008R2 中工作,但我使用以下方法将时间切片降低到毫秒:

DATEADD(MILLISECOND, -DATEDIFF(MILLISECOND, CAST(time AS DATE), time) % @msPerSlice, time)

其工作原理是:

  • 获取固定点和目标时间之间的毫秒数:
    @ms = DATEDIFF(MILLISECOND, CAST(time AS DATE), time)
  • 取这些毫秒除以时间片后的余数:
    @rms = @ms % @msPerSlice code>
  • 将余数的负数添加到目标时间以获得切片时间:
    DATEADD(MILLISECOND, -@rms, time)

不幸的是,由于微秒和更小的单位会溢出,因此,更大、更精细的数据集需要使用不太方便的定点。

我没有对此进行严格的基准测试,而且我也不从事大数据工作,因此您的里程可能会有所不同,但性能并没有比在我们的设备和数据集上尝试的其他方法明显差,而且开发人员可以方便地进行任意切片,这使得它值得对于我们来说。

For SQL Server 2012, though I believe it would work in SQL Server 2008R2, I use the following approach to get time slicing down to the millisecond:

DATEADD(MILLISECOND, -DATEDIFF(MILLISECOND, CAST(time AS DATE), time) % @msPerSlice, time)

This works by:

  • Getting the number of milliseconds between a fixed point and target time:
    @ms = DATEDIFF(MILLISECOND, CAST(time AS DATE), time)
  • Taking the remainder of dividing those milliseconds into time slices:
    @rms = @ms % @msPerSlice
  • Adding the negative of that remainder to the target time to get the slice time:
    DATEADD(MILLISECOND, -@rms, time)

Unfortunately, as is this overflows with microseconds and smaller units, so larger, finer data sets would need to use a less convenient fixed point.

I have not rigorously benchmarked this and I am not in big data, so your mileage may vary, but performance was not noticeably worse than the other methods tried on our equipment and data sets, and the payout in developer convenience for arbitrary slicing makes it worthwhile for us.

静谧幽蓝 2024-10-24 11:16:53
select from_unixtime( 600 * ( unix_timestamp( [Date] ) % 600 ) ) AS RecT, avg(Value)
from [FRIIB].[dbo].[ArchiveAnalog]
group by RecT
order by RecT;

将两个 600 替换为您想要分组的任意秒数。

如果您经常需要此操作并且表不会更改,正如名称 Archive 所暗示的那样,将日期(和时间)转换并存储为表中的 unixtime 可能会更快一些。

select from_unixtime( 600 * ( unix_timestamp( [Date] ) % 600 ) ) AS RecT, avg(Value)
from [FRIIB].[dbo].[ArchiveAnalog]
group by RecT
order by RecT;

replace the two 600 by any number of seconds you want to group.

If you need this often and the table doesn't change, as the name Archive suggests, it would probably be a bit faster to convert and store the date (& time) as a unixtime in the table.

忆梦 2024-10-24 11:16:53

我知道我在这个节目上迟到了,但我使用了这个 - 非常简单的方法。这样您就可以获得 60 分钟的切片,而不会出现任何舍入问题。

Select 
   CONCAT( 
            Format(endtime,'yyyy-MM-dd_HH:'),  
            LEFT(Format(endtime,'mm'),1),
            '0' 
          ) as [Time-Slice]

I know I am late to the show with this one, but I used this - pretty simple approach. This allows you to get the 60 minute slices without any rounding issues.

Select 
   CONCAT( 
            Format(endtime,'yyyy-MM-dd_HH:'),  
            LEFT(Format(endtime,'mm'),1),
            '0' 
          ) as [Time-Slice]
看海 2024-10-24 11:16:53
select dateadd(minute, datediff(minute, 0, Date), 0),
       sum(SnapShotValue)
FROM [FRIIB].[dbo].[ArchiveAnalog]
group by dateadd(minute, datediff(minute, 0, Date), 0)
select dateadd(minute, datediff(minute, 0, Date), 0),
       sum(SnapShotValue)
FROM [FRIIB].[dbo].[ArchiveAnalog]
group by dateadd(minute, datediff(minute, 0, Date), 0)
幸福还没到 2024-10-24 11:16:53

尝试这个查询。它构成一列。 (参考@nobilist的回答)

GROUP BY CAST(DATE(`your_date_field`) as varchar) || ' ' || CAST(HOUR(`your_date_field`) as varchar) || ':' || CAST(FLOOR(minute(`your_date_field`) / 10) AS varchar) || '0' AS date_format

Try this query. It makes one column. (references @nobilist answer)

GROUP BY CAST(DATE(`your_date_field`) as varchar) || ' ' || CAST(HOUR(`your_date_field`) as varchar) || ':' || CAST(FLOOR(minute(`your_date_field`) / 10) AS varchar) || '0' AS date_format
甜警司 2024-10-24 11:16:53

以下选项提供了该时间间隔的人类可读的开始时间(7:30、7:40 等)。

在临时表中,它使用 SMALLDATETIME 截断秒和毫秒,然后主查询减去所需分钟间隔内的任何数量。

SELECT DATEADD(MINUTE, -(DATEDIFF(MINUTE, '2000', tmp.dt) % 10), tmp.dt)
FROM (
    SELECT CAST(DateField AS SMALLDATETIME) AS dt
    FROM MyDataTable
) tmp

也可以用一行代码完成,但可读性较差。

SELECT DATEADD(MINUTE, -(DATEDIFF(MINUTE, '2000', CAST(DateField AS SMALLDATETIME)) % 10), CAST(DateField AS SMALLDATETIME)) AS [interval] FROM MyDataTable

Here is an option that provides a human readable start time of that interval (7:30, 7:40, etc).

In a temp table, it truncates seconds and milliseconds by using SMALLDATETIME, and then the main query subtracts any amount over the desired minute interval.

SELECT DATEADD(MINUTE, -(DATEDIFF(MINUTE, '2000', tmp.dt) % 10), tmp.dt)
FROM (
    SELECT CAST(DateField AS SMALLDATETIME) AS dt
    FROM MyDataTable
) tmp

It can also be done in a single line of code, but it is not as readable.

SELECT DATEADD(MINUTE, -(DATEDIFF(MINUTE, '2000', CAST(DateField AS SMALLDATETIME)) % 10), CAST(DateField AS SMALLDATETIME)) AS [interval] FROM MyDataTable
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文