2015-07-19 71 views
1

假設我給出了startTimeendTime,並且這些間隔爲半小時。例如startTime=8:00,endTime=12:00所以可能的時間是8:00, 8:30, 9:00, 9:30, 10:00, 10:30, 11:00, 11:30, 12:00按發生次數分組的時間間隔

現在我有我的動作發生的時間段行的行。每行有rowStartTime和rowEndTime。 他們是類型TIME

我試圖實現的事情是返回GROUPED結果的時間與在該特定時間發生的行數。

演示數據

name rowStarTime rowEndTime 
-------------------------------- 
action1 6:00  10:00 
action2 9:00  13:00 
action3 10:00  11:30 
action4 12:00  13:00 
action5 11:30  15:00 

預期結果

Time  Action count (actions in that time, this is just comment) 
--------------------------------------------------------------------- 
8:00  1    //1 
8:30  1    //1 
9:00  2    //1, 2 
9:30  2    //1, 2 
10:00  3    //1, 2, 3 
10:30  2    //2, 3 
11:00  2    //2, 3 
11:30  3    //2, 3, 5 
12:00  4    //2, 4, 5 

我想要做的大部分在數據庫級別上(使用SQL)。它可行嗎?或者我必須得到一些PHP的幫助(我使用Doctrine DQL,但是我可以使用很多特殊的SQL函數https://github.com/orocrm/doctrine-extensions & https://github.com/beberlei/DoctrineExtensions)?

我才能夠達到這一目的rowStartTime,而不是整個週期:

SELECT `rowStartTime` AS sclr_0, COUNT(o.id) AS sclr_1 
FROM orders o 
GROUP BY sclr_0 

(如果只選擇startTimeendTime倍之間將很難,這不是核心,可以省略這個條件)

回答

2
DROP TABLE IF EXISTS my_table; 

CREATE TABLE my_table 
(name VARCHAR(12) NOT NULL PRIMARY KEY 
,start_time TIME NOT NULL 
,end_time TIME NOT NULL 
); 

INSERT INTO my_table VALUES 
('action1', '6:00:00','10:00:00'), 
('action2', '9:00:00','13:00:00'), 
('action3','10:00:00','11:30:00'), 
('action4','12:00:00','13:00:00'), 
('action5','11:30:00','15:00:00'); 

SELECT * FROM my_table; 
+---------+------------+----------+ 
| name | start_time | end_time | 
+---------+------------+----------+ 
| action1 | 06:00:00 | 10:00:00 | 
| action2 | 09:00:00 | 13:00:00 | 
| action3 | 10:00:00 | 11:30:00 | 
| action4 | 12:00:00 | 13:00:00 | 
| action5 | 11:30:00 | 15:00:00 | 
+---------+------------+----------+ 

SELECT * FROM ints; 
+---+ 
| i | 
+---+ 
| 0 | 
| 1 | 
| 2 | 
| 3 | 
| 4 | 
| 5 | 
| 6 | 
| 7 | 
| 8 | 
| 9 | 
+---+ 

SELECT SEC_TO_TIME(1800*(i2.i*10+i1.i)) time 
    , COUNT(*) total 
    , GROUP_CONCAT(x.name) actions 
    FROM ints i1 
CROSS 
    JOIN ints i2 
    LEFT 
    JOIN my_table x 
    ON SEC_TO_TIME(1800*(i2.i*10+i1.i)) BETWEEN x.start_time AND x.end_time 
WHERE SEC_TO_TIME(1800*(i2.i*10+i1.i)) BETWEEN '08:00:00' AND '12:00:00' 
GROUP 
    BY time; 
+----------+-------+-------------------------+ 
| time  | total | actions     | 
+----------+-------+-------------------------+ 
| 08:00:00 |  1 | action1     | 
| 08:30:00 |  1 | action1     | 
| 09:00:00 |  2 | action1,action2   | 
| 09:30:00 |  2 | action1,action2   | 
| 10:00:00 |  3 | action1,action2,action3 | 
| 10:30:00 |  2 | action2,action3   | 
| 11:00:00 |  2 | action2,action3   | 
| 11:30:00 |  3 | action2,action3,action5 | 
| 12:00:00 |  3 | action2,action4,action5 | 
+----------+-------+-------------------------+ 
1

創建活動表

CREATE TABLE actions (a VARCHAR(50), start TIME, end TIME); 
INSERT INTO actions (a,start,end) VALUES 
('action 1', '6:00', '10:00'), 
('action 2', '9:00', '13:00'), 
('action 3', '10:00', '11:30'), 
('action 4', '12:00', '13:00'), 
('action 5', '11:30', '15:00'); 

的時間創建時間表

CREATE TABLE times (t TIME); 
INSERT INTO times (t) VALUES 
('5:00'), ('5:30'), 
('6:00'), ('6:30'), 
('7:00'), ('7:30'), 
('8:00'), ('8:30'), 
('9:00'), ('9:30'), 
('10:00'), ('10:30'), 
('11:00'), ('11:30'), 
('12:00'), ('12:30'), 
('13:00'), ('13:30'), 
('14:00'), ('14:30'), 
('15:00'), ('15:30'); 

選擇

SELECT 
times.t as t, 
count(CASE WHEN actions.a IS NOT NULL THEN 1 ELSE NULL END) as c 
FROM times 
LEFT JOIN actions ON actions.start <= times.t AND actions.end >= times.t 
GROUP BY times.t 

結果

t   c 
05:00:00 0 
05:30:00 0 
06:00:00 1 
06:30:00 1 
07:00:00 1 
07:30:00 1 
08:00:00 1 
08:30:00 1 
09:00:00 2 
09:30:00 2 
10:00:00 3 
10:30:00 2 
11:00:00 2 
11:30:00 3 
12:00:00 3 
12:30:00 3 
13:00:00 3 
13:30:00 1 
14:00:00 1 
14:30:00 1 
15:00:00 1 
15:30:00 0 
1

在一定時間間隔創建temporay表並使用

CREATE TEMPORARY TABLE TEMP (half TIME); 
DROP PROCEDURE IF EXISTS insertTEMP; 
DELIMITER // 
CREATE PROCEDURE insertTEMP (first TIME, last TIME) begin 
WHILE first <= last DO 
INSERT INTO TEMP Values (first); 
SET first = ADDTIME(first, "00:30"); 
END WHILE; 
END // 
DELIMITER ; 

CALL insertTEMP("04:00", "12:00"); 
SELECT TEMP.half `Time`, COUNT(actions.name) `count`, GROUP_CONCAT(actions.name) actions FROM (TEMP, actions) WHERE TEMP.half between actions.rowStarTime AND actions.rowEndTime GROUP BY half 

正如你所看到的,沒有行動的時間不包括在結果中

Time, count, actions 
06:00:00, 1, action1 
06:30:00, 1, action1 
07:00:00, 1, action1 
07:30:00, 1, action1 
08:00:00, 1, action1 
08:30:00, 1, action1 
09:00:00, 2, action1,action2 
09:30:00, 2, action1,action2 
10:00:00, 3, action1,action2,action3 
10:30:00, 2, action2,action3 
11:00:00, 2, action2,action3 
11:30:00, 3, action2,action3,action5 
12:00:00, 3, action2,action4,action5