2013-02-11 65 views
1

我有一个表,其中一列是日期:MySQL的计数相同的间隔内的行海誓山盟

+----------+---------------------+ 
|  id |    date | 
+----------+---------------------+ 
|  5 | 2012-12-10 10:12:37 |   
+----------+---------------------+ 
|  4 | 2012-12-10 09:09:55 |   
+----------+---------------------+ 
|  3 | 2012-12-09 21:12:35 |   
+----------+---------------------+ 
|  2 | 2012-12-09 20:15:07 |   
+----------+---------------------+ 
|  1 | 2012-12-09 20:01:42 |   
+----------+---------------------+ 

我需要什么,是计数其例如whitin 3小时,以彼此的行。在这个例子中,我想加入第二行的上一行,第四行和第五行的第三行。所以我的输出应该是这样的:

+----------+---------------------+---------+ 
|  id |    date | count | 
+----------+---------------------+---------+ 
|  5 | 2012-12-10 10:12:37 |  2 | 
+----------+---------------------+---------+ 
|  3 | 2012-12-09 21:12:35 |  3 | 
+----------+---------------------+---------+ 

我怎么能这样做?

+0

那么,[**你有什么**](http:// www .whathaveyoutried.com)? – Kermit 2013-02-11 19:55:06

回答

0

我认为你需要自连接此:(这是未经测试的代码,以便它可能有一个语法错误)

select t.id, t.date, COUNT(t2.id) 
from t left outer join 
    t t2 
    on t.date between t2.date - interval 3 hour and t2.date + interval 3 hour 
group by t.id, t.date 

如果你正在尝试一切分为3-小时一班,你可以这样做:

select max(t.date), t.id, count(*) 
from (select t.*, 
      (date(date)*100 + floor(hour(date)/3)*3) as interval 
     from t 
    ) t 
group by interval 
+0

根据问题中的示例,它将返回5行而不是2 ....每个ID的每行... – 2013-02-11 21:28:14

+0

@NitinMidha。 。 。您的原始*问题*不是关于过滤或分组行,而是关于在3小时内查找计数。你可以每2小时记录一次,而且它们都会链接在一起。我以固定的时间间隔回答了问题。 – 2013-02-11 21:39:10

+0

在他的预期产出中,他将第4行和第5行合并为第5行,第1,2行和第3行合并为第3行。 – 2013-02-11 22:22:43

0

我不知道如何使用我的SQL做到这一点,但我能够建立一组查询的SQL Server 2005中,将提供预期的结果。这里是工作样本,其非常复杂,可能过于复杂,但这就是我如何能够得到所需结果:

WITH BaseData AS 
(
    SELECT 5 AS ID, '2012-12-10 10:12:37' AS Date 
    UNION ALL 
    SELECT 4 AS ID, '2012-12-10 09:09:55' AS Date 
    UNION ALL 
    SELECT 3 AS ID, '2012-12-09 21:12:35' AS Date 
    UNION ALL 
    SELECT 2 AS ID, '2012-12-09 20:15:07' AS Date 
    UNION ALL 
    SELECT 1 AS ID, '2012-12-09 20:01:42' AS Date 
), 
BaseDataWithRowNum AS 
(
    SELECT ID,DATE, ROW_NUMBER() OVER (ORDER BY Date DESC) AS RowNum 
     FROM BaseData 
), 
InterRelatedDates AS 
(
    SELECT B1.RowNum AS RowNum1,B2.RowNum AS RowNum2 
     FROM BaseDataWithRowNum B1 
    INNER JOIN BaseDataWithRowNum B2 
     ON B1.Date BETWEEN B2.Date AND DATEADD(hh,3,B2.Date) 
     AND B1.RowNum < B2.RowNum 
     AND B1.ID != B2.ID 
), 
InterRelatedDatesWithinMultipleGroups AS 
(
    SELECT G1.RowNum1,G2.RowNum2 
     FROM InterRelatedDates G1 
     LEFT JOIN InterRelatedDates G2 
     ON G1.RowNum2 = G2.RowNum2 
     AND G1.RowNum1 != G2.RowNum1 
) 


SELECT BN.ID, 
     BN.Date, 
     CountExcludingOriginalGrouppingRecord +1 AS C 
    FROM 
     (
     SELECT RowNum1 AS RowNum,COUNT(1) AS CountExcludingOriginalGrouppingRecord 
      FROM 
       (
       -- If a row was used in only one group then it is ok. use as it is 
       SELECT D1.RowNum1 
        FROM InterRelatedDatesWithinMultipleGroups AS D1 
       WHERE D1.RowNum2 IS NULL 

       UNION ALL 

       -- In case a row was selected in two groups, choose the one with higher date 
       SELECT Min(D1.RowNum1) 
        FROM InterRelatedDatesWithinMultipleGroups AS D1 
       WHERE D1.RowNum2 IS NOT NULL 
       GROUP BY D1.RowNum2 
      ) T 
     GROUP BY RowNum1 
    ) T2 
INNER JOIN BaseDataWithRowNum BN 
    ON BN.RowNum = T2.RowNum