T-SQL不同的关闭日期

时间:2016-01-29 16:15:36

标签: sql-server tsql sql-server-2005

使用SQL Server 2005我使用UNION从一组两个表中选择DATETIME。其中许多非常接近:例如:

2016-01-29 10:28:57.540
2016-01-29 10:28:57.647
2016-01-29 11:23:18.193
2016-01-29 11:23:18.240

在这个例子中,我想回来

2016-01-29 10:28:57.000  
2016-01-29 11:23:18.000

使用某些日期/转换功能删除ms部分很容易。但是,如果我们得到以下内容:

2016-01-29 10:18:58.105
2016-01-29 10:18:57.952
2016-01-29 11:13:18.193
2016-01-29 11:13:18.240

当我只想要2:

时,我会得到3个日期时间
2016-01-29 10:18:58.000
2016-01-29 10:18:57.000
2016-01-29 11:13:18.000

而不是:

2016-01-29 10:18:58.000
2016-01-29 11:13:18.000

2016-01-29 10:18:58.105和2016-01-29 10:18:57.952不到一秒钟。

所以问题是我如何将DATETIME值组合在一起呢?

4 个答案:

答案 0 :(得分:3)

MS SQL 2005更新

DECLARE @TestDate AS TABLE (
    dt DATETIME NOT NULL
)

INSERT INTO @TestDate (dt)
VALUES 
('2016-01-29 10:18:58.105')
,('2016-01-29 10:18:57.952')
,('2016-01-29 11:13:18.193')
,('2016-01-29 11:13:18.240')


;WITH IdDt AS (
    SELECT Id = ROW_NUMBER() OVER (ORDER BY dt)
            ,dt
    FROM @TestDate)

SELECt IdDt.dt
FROM IdDt
    LEFT JOIN IdDt LagDt ON IdDt.ID = LagDt.ID + 1
WHERE CASE WHEN DATEDIFF(MILLISECOND, LagDt.dt, IdDt.dt) < 1000 Then 0 ELSE 1 END = 1

MS SQL Server 2012 +

MSDN Analytic function LAG()

DECLARE @TestDate AS TABLE (
    dt DATETIME NOT NULL
)

INSERT INTO @TestDate (dt)
VALUES 
('2016-01-29 10:18:58.105')
,('2016-01-29 10:18:57.952')
,('2016-01-29 11:13:18.193')
,('2016-01-29 11:13:18.240')

SELECT dt
FROM (
    SELECT dt, CASE WHEN DATEDIFF(MILLISECOND, LAG(dt) OVER (ORDER BY dt), dt) < 1000 Then 0 ELSE 1 END ToRemove
    FROM @TestDate
    ) Filter
WHERE ToRemove = 1;

答案 1 :(得分:1)

决定如何修剪微秒,然后按选择的功能分组

select
    DT,
    -- Round down to nearest second
    DT_Floor_MS =
        dateadd(ms,-datepart(ms,a.DT),a.DT),
    -- Round up to nearest second
    DT_Ceiling_MS = 
        dateadd(ms,(1000-datepart(ms,a.DT))%1000,a.DT),
    -- Round to nearest second
    DT_Round_Off_MS =
        dateadd(ms,500-((datepart(ms,a.DT)+500)%1000),a.DT)
from
    (select --test data
        '2016-01-29 10:28:57.540' DT union all select
        '2016-01-29 10:28:57.647'union all select
        '2016-01-29 11:23:18.193'union all select
        '2016-01-29 11:23:18.240' ) a

&#13;
&#13;
DT	                DT_Floor_MS	                DT_Ceiling_MS	                DT_Round_Off_MS
2016-01-29 10:28:57.540	January, 29 2016 10:28:57	January, 29 2016 10:28:58	January, 29 2016 10:28:58
2016-01-29 10:28:57.647	January, 29 2016 10:28:57	January, 29 2016 10:28:58	January, 29 2016 10:28:58
2016-01-29 11:23:18.193	January, 29 2016 11:23:18	January, 29 2016 11:23:19	January, 29 2016 11:23:18
2016-01-29 11:23:18.240	January, 29 2016 11:23:18	January, 29 2016 11:23:19	January, 29 2016 11:23:18
&#13;
&#13;
&#13;

select 

        dateadd(ms,(1000-datepart(ms,a.DT))%1000,a.DT)
    -- Round to nearest second      
        from
    (select --test data
        '2016-01-29 10:28:57.540' DT union all select
        '2016-01-29 10:28:57.647'union all select
        '2016-01-29 11:23:18.193'union all select
        '2016-01-29 11:23:18.240' ) a

    group by

        dateadd(ms,(1000-datepart(ms,a.DT))%1000,a.DT)
    -- Round to nearest second  

2016-01-29 10:28:58.000
2016-01-29 11:23:19.000

答案 2 :(得分:0)

为我的目的找到答案:

SELECT t1.UpdatedDateTime 
FROM MyTable t1 
LEFT JOIN MyTable t2 ON t1.UpdatedDateTime > t2.UpdatedDateTime AND t1.UpdatedDateTime < DATEADD(SECOND,1,t2.UpdatedDateTime)
WHERE t2.UpdatedDateTime IS NULL

将表格连接在一起只会带回另一行的行,并且在下一秒内有一段时间。

答案 3 :(得分:0)

最简单,最直接的方法是使用日期时间第二近似值的区别如下:

SELECT DISTINCT DATEADD(MILLISECOND, 500 - DATEPART(MILLISECOND, TimeField + '00:00:00.500'),TimeField)  FROM T1

演示: http://sqlfiddle.com/#!3/b208c/3