2013-02-11 66 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