2014-03-25 39 views
4

我有一個MySQL數據庫,每15分鐘記錄一次數據。爲了簡單起見,讓我們假設有2個字段:爲時間序列數據創建小時組MySQL

DATETIME Created 
Double Value 

我要提請這就需要用於每個小時的開口,最小值,最大值,和關閉值一小時的圖表。爲此,我需要將我的MySQL查詢結果返回給我的PHP來創建一個JSON。我想在MySQL查詢中這樣做,以便響應被緩存。

這是問題的一個例子,給出9個數據點,試圖讓2小時組:

Creation   Value 
2014-03-25 12:15:00 413.17011 
2014-03-25 12:00:00 414 
2014-03-25 11:45:00 415 
2014-03-25 11:30:00 415 
2014-03-25 11:15:00 415.5 
2014-03-25 11:00:00 415.5 
2014-03-25 10:45:00 416 
2014-03-25 10:30:00 416 
2014-03-25 10:15:00 415.99 

我需要:

Hour 1 (11:15:00 to 12:15:00) 
Open: 415.5 
Close: 413.17011 
High: 415.5 
Low: 413.17011 

Hour 2 (10:15:00 to 11:15:00) 
Open: 415.99 
Close: 415.5 
High: 416 
Low: 415.5 

當然了整整24個小時本會需要重複,這只是一個例子。 任何幫助真的很感激!

下面是例子(使用MySQL版本2.6.4-PL3)當前的MySQL轉儲:

-- 
-- Table structure for table `exampleTable` 
-- 

CREATE TABLE `exampleTable` (
    `created` datetime NOT NULL, 
    `value` double NOT NULL 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci; 

-- 
-- Dumping data for table `exampleTable` 
-- 

INSERT INTO `exampleTable` VALUES ('2014-03-25 12:15:00', 413.17011); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 12:00:00', 414); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 11:45:00', 415); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 11:30:00', 415); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 11:15:00', 415.5); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 11:00:00', 415.5); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 10:45:00', 416); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 10:30:00', 416); 
INSERT INTO `exampleTable` VALUES ('2014-03-25 10:15:00', 415.99); 
+0

缺乏響應擔心我,所以我會盡我所能縮短這個問題 – ThePerson

+1

正如提示:如果可以的話,你可能會想把日期和時間分成兩列('date'和'time'類型),這樣你就不需要每次都在'created'上投入'DATE()',而是可以使用新的日期列。然後添加一個索引到這個列也是,這加快了你的查詢。[見這個sqlfiddle的例子](http://sqlfiddle.com/#!2/5f117/2) – GhostGambler

+0

甚至更​​好:[兩者的組合索引新列](http://sqlfiddle.com/#!2/7f282/1)。避免兩個文件 – GhostGambler

回答

2

得到它的工作

你可以嘗試

SELECT 
DATE(created) AS day, 
HOUR(created) AS hour, 
(
    SELECT Value FROM `table` AS b 
    WHERE DATE(a.created) = DATE(b.created) 
    AND HOUR(a.created) = HOUR(b.created) 
    ORDER BY created ASC LIMIT 1 
) AS Open, 
(
    SELECT Value FROM `table` AS b 
    WHERE DATE(a.created) = DATE(b.created) 
    AND HOUR(a.created) = HOUR(b.created) 
    ORDER BY created DESC LIMIT 1 
) AS Close, 
MIN(value) AS Low, 
MAX(value) AS High 
FROM `table` AS a 
GROUP BY DATE(created), HOUR(created) 

這將所有行按DATE + HOUR分組,然後分別計算MAX分別爲LowHigh。要找到OpenClose的第一行和最後一行,最簡單的SQL語法是子查詢。它選擇與當前行相關的所有行,並對它們進行升序或降序排序。然後選擇第一行。

請認爲這個小組只有小時。取而代之的

Hour 1 (11:15:00 to 12:15:00) 
Hour 2 (10:15:00 to 11:15:00) 

這個羣體喜歡

Hour 1 (11:00:00 to 11:59:00) 
Hour 2 (10:00:00 to 10:59:00) 

如果你想保持15分鐘偏差,您可以從您所創建的時間戳(created - INTERVAL 15 MINUTE)在created所有出現在SQL查詢中減去這個上面。

我爲您創建了a working sqlfiddle

性能

正如提示:如果可以的話,你可能想的日期和時間分爲兩列(類型datetime)。這種方式你不需要每次都在created上投DATE(),而是可以使用新的日期列。然後,您可以將組合索引添加到這些新列中,從而加快查詢速度。以this sqlfiddle爲例。

+0

這看起來會讓我非常接近我的目標是讓它基於最近的時間間隔秒。因此,例如,如果時間現在是09:36,則應該將08:30至09:30顯示爲一個組。然後在07:30到08:30之間。如果我使用這個代碼,也許我可以先計算偏移量。我將對此有所瞭解,看看我是否可以改變它,並且我非常感謝你的幫助(Upvote給出了,如果/當我設法讓它起作用,我會接受它) – ThePerson

+1

當然。如果您遇到任何問題,請告訴我們。 – GhostGambler

+0

感謝GhostGambler。我改變了我的表格,我正在測試使用相同的字段名稱作爲您的工作(值和創建和表名稱「表」),但我似乎得到一個語法錯誤。它說: #1064 - 你的SQL語法有錯誤;檢查對應於您的MySQL服務器版本的手冊,以找到正確的語法,以便在第5行附近使用'table AS b WHERE DATE(a.created)= DATE(b.created) AND HOUR(a.created)' 我將添加數據庫表結構作爲MySQL轉儲的問題,這可能是我做錯了或解釋錯誤的東西。 – ThePerson

1

爲了讓您的分組的權利,你可以使用

FLOOR((UNIX_TIMESTAMP(myTable.dateCreated) - 900)/3600) 

,其中3600在1小時,設定的時間間隔 - 900套00:15

偏移既然你需要的MIN()和MAX分別代表你的四個值,你需要將主表加入自己,但是按最小或最大(基於列)進行分組。

最後,你有每個子查詢(連接表)計算上面的分組小時,所以你可以用它來加入它們。這是我凸輪了(略有不同的列名和

SELECT openDate,Open,Close,High,Low 
FROM (SELECT FLOOR((UNIX_TIMESTAMP(myTable.dateCreated) - 900)/3600) 
       AS 
         theHour, 
         myTable.value AS Open,myTable.dateCreated openDate 
     FROM myTable 
       JOIN (SELECT value,MIN(dateCreated) AS dateCreated 
        FROM myTable 
        GROUP BY FLOOR((UNIX_TIMESTAMP(dateCreated) - 900) 
            /3600) 
        ) AS 
            aggTable 
       ON aggTable.dateCreated = myTable.dateCreated) AS 
     openTable 
     LEFT JOIN (SELECT FLOOR((UNIX_TIMESTAMP(myTable.dateCreated) - 900 
           )/
           3600) AS 
     theHour 
     , 
     myTable.value AS Close,myTable.dateCreated closeDate 
     FROM myTable 
     JOIN (SELECT value,MAX(dateCreated) AS dateCreated 
     FROM myTable 
     GROUP BY FLOOR((UNIX_TIMESTAMP(dateCreated) - 900)/3600) 
     ) AS 
     aggTable 
     ON aggTable.dateCreated = myTable.dateCreated) AS closeTable 
       ON openTable.theHour = closeTable.theHour 
     LEFT JOIN (SELECT 
                 FLOOR(( 
       UNIX_TIMESTAMP(myTable.dateCreated) - 900)/3600) AS 
        theHour, 
                  MAX( 
                    value) 
       AS High 
        FROM myTable 
        GROUP BY theHour) AS highTable 
       ON closeTable.theHour = highTable.theHour 
     LEFT JOIN (SELECT 
                 FLOOR(( 
       UNIX_TIMESTAMP(myTable.dateCreated) - 900)/3600) AS 
        theHour, 
                  MIN( 
                    value) 
       AS Low 
        FROM myTable 
        GROUP BY theHour) AS lowTable 
       ON highTable.theHour = lowTable.theHour 
+0

感謝您 - 它看起來不錯。我需要一點時間來理解它的工作原理,但我會花一些時間來理解它。 – ThePerson

+1

重要的是把它看作一個外部查詢和4個內部查詢,每個內部查詢都有一個連接,所以它看起來很怪異,但它的模式真的是一遍又一遍地重複着,只有輕微的變化獲取您想要的頂欄的值。對不起,這是一團糟。我跑過了一個美化師,可能不太適合SO。 – Anthony