SQL组按日期差异

时间:2013-10-23 16:07:11

标签: sql sql-server tsql group-by

我在写下面的SQL查询时遇到困难。 我有一张桌子:

id | C1 | C2 | date

1  | 1  | 1  | 1/10/2010 9:30:10
2  | 1  | 1  | 1/10/2010 9:31:10
3  | 1  | 1  | 1/10/2010 9:32:10
4  | 1  | 1  | 1/10/2010 9:37:10
5  | 1  | 2  | 1/10/2010 9:38:10
6  | 2  | 3  | 1/10/2010 9:39:10
7  | 2  | 3  | 1/10/2010 9:45:10
8  | 2  | 3  | 1/10/2010 9:46:10

现在我想获取如下记录:
按日期差异(最新日期)分组记录5分钟,同一C1和同一C2 (即记录如同相同C1的每个C2的5分钟内的latset日期) 我只想输出:

id | C1 | C2 | date

3  | 1  | 1  | 1/10/2010 9:32:10
4  | 1  | 1  | 1/10/2010 9:37:10
5  | 1  | 2  | 1/10/2010 9:38:10
6  | 2  | 3  | 1/10/2010 9:39:10
7  | 2  | 3  | 1/10/2010 9:46:10

说明:
1.前3条记录分组(同一C1和5分钟内相同的C2)和第3条记录(最新的3条记录)。
2. 4记录取。 (它是向后5分钟内的唯一记录,同一C1和同一C2的前5分钟) 3.与上述相同
同样高达......第8记录 我尝试了各种分组和查询分区,但被卡住了。任何帮助,将不胜感激。谢谢

2 个答案:

答案 0 :(得分:2)

可能有一个更简单的解决方案,但我使用了一个公用表表达式checktimesagainsttimes来检查针对同一个表连接的一个记录的前进和后退。如果我的数据位于名为test3的表中,则将数据视为表m2,将其作为表m1连接到其自身以及作为表m3之后的记录。

它会比较m1,m2和m3中的日期,并返回一个列checktimesagainsttimes的表WithinFiveMinutes,如果它在前一个或下一个记录的五分钟内,则返回1。

然后我使用另一个公用表表达式来查询checktimesagainsttimes两次。我第一次获得他们在五分钟内的组的最长日期。然后我将结果与checktimesagainsttimes的结果联合起来,这些结果彼此不在五分钟之内。这些结果将在5分钟内恢复到最大值。

最后要做的是获取这些结果,并根据c1,c2和日期返回原始表格,以取回实际的rowed

WITH    checktimesagainsttimes
          AS ( SELECT   m2.id AS id2 ,
                        m1.id AS id1 ,
                        m3.id AS id3 ,
                        m2.date ,
                        m2.c1 ,
                        m2.c2 ,
                        CASE WHEN ( DATEADD(mi, 5, m2.date) > m3.date
                                    AND m2.date < m3.date
                                  )
                                  OR ( DATEADD(mi, -5, m2.date) < m1.date
                                       AND m2.date > m1.date
                                     ) THEN 1
                             ELSE 0
                        END AS WithinFiveMinutes
               FROM     test3 m2
                        LEFT OUTER JOIN test3 m1 ON m2.c1 = m1.c1
                                                    AND m2.c2 = m1.c2
                                                    AND ( m2.id = m1.id
                                                          + 1 )
                        LEFT OUTER JOIN test3 m3 ON m2.c1 = m3.c1
                                                    AND m2.c2 = m3.c2
                                                    AND ( m2.id = m3.id
                                                          - 1 )
             ),
        maxdatesforwithin5minutes
          AS ( SELECT   c1 ,
                        c2 ,
                        MAX(date) AS date
               FROM     checktimesagainsttimes
               WHERE    WithinFiveMinutes = 1
               GROUP BY c1 ,
                        c2 ,
                        withinFiveMinutes
               UNION
               SELECT   c1 ,
                        c2 ,
                        date
               FROM     checktimesagainsttimes
               WHERE    WithinFiveMinutes = 0
             )
    SELECT  t.id ,
            t.c1 ,
            t.c2 ,
            t.date
    FROM    maxdatesforwithin5minutes m
            INNER JOIN test3 t ON m.c1 = t.c1
                                  AND m.c2 = t.c2
                                  AND m.date = t.date

答案 1 :(得分:1)

尝试

SELECT MAX(id), C1, C2, MAX([date])
FROM tbl
GROUP BY C1, C2, DATEADD(MINUTE, DATEDIFF(MINUTE,0,[date]) / 5 * 5, 0)