2016-06-16 75 views
2

你好,我堅持這一點。希望能夠從mySQL數據庫中的兩個啓動/停止行之間抽出時間。我的表看起來像這樣PHP mySQL行之間的時間

fillercdown_ndx | time     | B3_4_5 
1    | 2016-06-16 14:59:45 | 0 
2    | 2016-06-16 15:03:11 | 1 

基本上,當其記錄爲0時,機器停止,當記錄爲1時,機器重新啓動。我需要能夠計算機器在特定時間(如上午8點至下午5點)之間停機的時間。打算使用PHP在用戶輸入時顯示它,但不知道SQL命令。

任何人都知道能夠找到它的最好方法嗎?

創建表

CREATE TABLE `fillercdown` (
`fillercdown_ndx` int(11) NOT NULL AUTO_INCREMENT, 
`time` datetime DEFAULT NULL, 
`B3_4_5` int(11) DEFAULT NULL, 
PRIMARY KEY (`fillercdown_ndx`), 
KEY `fillercdowntimendx` (`time`) 
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 

UPDATE:

將有上百個這樣的 「開始」 和 「停止」 的條目。我的最終目標是在php中爲用戶提供一個小表單,要求他們提供一個時間範圍,例如8 AM-5PM,然後能夠計算機器「停止」的所有時間(B3_4_5爲0時)。我似乎無法弄清楚正確的SQL調用,以獲得每個0和1之間的時間差,並將它們添加在一個設定的時間範圍內

+0

我假設'fillercdown_ndx'是主鍵......你能不能添加'CREATE TABLE'這個表你的問題?另外:你是否想知道從特定的'0'到下一個出現'1'的持續時間,即:你知道'fillercdown_ndx'嗎? b)來自所有? c)平均? – Centril

+0

更新我希望這解釋更多。對不起,我真的還在學習,但盡我所能。這就讓我卡住了 –

+0

所以如果我正確地理解了這個問題,你想在小時X和Y內選擇所有(0,1)對,然後計算這些間隔的總和? – Centril

回答

0

這是基本思想......它將結果選擇爲單row and, which you can then fetch with PHP` ...

此解決方案假定停止&開始成對出現的,即:一開始的ID將是+1是停止的。否則,你應該SELECT/JOIN的ID是>那個停止的,並且LIMIT它到1

自加入可能不會產生最佳的性能,所以要小心並測量一些數據的執行時間以確保安全。

http://sqlfiddle.com/#!9/de72bf/1

CREATE TABLE fillercdown (
`fillercdown_ndx` int(11) NOT NULL AUTO_INCREMENT, 
`time` datetime DEFAULT NULL, 
`B3_4_5` int(11) DEFAULT NULL, 
    PRIMARY KEY (`fillercdown_ndx`), 
    KEY `fillercdowntimendx` (`time`) 
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=latin1; 

INSERT INTO fillercdown 
    (`time`, `B3_4_5`) 
VALUES 
    ('2016-06-16 14:00:45', 0), 
    ('2016-06-16 14:01:00', 1), 
    ('2016-06-16 16:00:00', 0), 
    ('2016-06-16 16:01:00', 1) 
    ; 

SELECT SUM(TIMEDIFF(g.`time`, f.`time`)) 
FROM fillercdown f 
INNER JOIN fillercdown g 
    ON g.`fillercdown_ndx` = (f.`fillercdown_ndx` + 1) 
    AND g.`B3_4_5` = 1 
    AND TIME(g.`time`) BETWEEN '08:00:00' AND '17:00:00' 
WHERE f.`B3_4_5` = 0 
    AND TIME(f.`time`) BETWEEN '08:00:00' AND '17:00:00' 

如果你想包括倍所在的機器停止,但尚未重新啓動,你可以做這樣的事情:

http://sqlfiddle.com/#!9/d113b9/9

INSERT INTO fillercdown 
    (`time`, `B3_4_5`) 
VALUES 
    ('2016-06-16 14:00:45', 0), 
    ('2016-06-16 14:01:00', 1), 
    ('2016-06-16 16:00:00', 0), 
    ('2016-06-16 16:01:00', 1), 
    ('2016-06-16 16:02:00', 0) 
    ; 

SELECT SUM(TIMEDIFF(COALESCE(g.`time`, '2016-06-16 16:02:01'), f.`time`)) 
FROM fillercdown f 
LEFT JOIN fillercdown g 
ON g.`fillercdown_ndx` = (f.`fillercdown_ndx` + 1) 
    AND g.`B3_4_5` = 1 
    AND TIME(g.`time`) BETWEEN '08:00:00' AND '17:00:00' 
WHERE TIME(f.`time`) BETWEEN '08:00:00' AND '17:00:00' AND f.`B3_4_5` = 0 

你可以取代2016-06-16 16:02:01NOW()或基於f.time的東西,它取決於當然你的應用需求。

如果您從不想獲得NULL,而是0,如果沒有匹配的行,請執行如下操作:COALESCE(SUM(...), 0)

如果你喜歡一個腳本型解決方案,你總是可以做這樣的事情:

SELECT f.`time`, f.`B3_4_5` 
FROM fillercdown f 
WHERE TIME(f.`time`) BETWEEN '08:00:00' AND '17:00:00' 

,然後計算總和,像這樣(僞代碼):

stopped = null; 
pairs = [] 
for (row in rows) 
    if (row.isStopped) stopped = row 
    else 
     pairs += [stopped, row] 
     stopped = null 

sum = 0 
for (pair in pairs) 
    sum += duration(pair[0], pair[1]) 
+0

你可能想要一個至少和最偉大的地方 – Strawberry

+0

@Strawberry請詳細說明,在哪裏?如果沒有匹配,則使結果爲非null或? – Centril

+0

另外,編輯答案,如果你可以改善它=) – Centril

0

這就是我目前用來做同樣的事情,這聽起來像你正在做的事情。我正在使用PDO,但如果您需要使用它,可以非常容易地對mysqli進行調整。這取決於按時間交替關閉/打開值。如果出於任何原因連續關閉或打開行,預期結果變得不明確。

// First select everything in the requested range ordered by time. 
$sql = "SELECT `time`, B3_4_5 FROM your_table WHERE `time` BETWEEN ? AND ? ORDER BY `time`"; 
$stmt = $pdo->prepare($sql); 
$stmt->execute([$query_start, $query_end]); 

// Initialize two DateTime objects (start and end) used to calculate the total time. 
$total_start = new DateTime('00:00'); 
$total_end = clone $total_start; 

$off = null; 
while ($row = $stmt->fetchObject()) { 
    if ($row->B3_4_5) { 
     $on = new DateTime($row->time); 
     // increment total end time with difference between current off/on times 
     if ($off) { 
      $total_end->add($on->diff($off)); 
     } 
    } else { 
     $off = new DateTime($row->time); 
    } 
} 

// total downtime is difference between start and end DateTimes 
$total_downtime = $total_start->diff($total_end); 

$total_downtimeDateInterval對象。你可以使用它的方法format返回消息:

echo $total_downtime->format('Total downtime: %h hours, %i minutes, %s seconds.'); 
+0

謝謝!爲我提供良好的方向,並可以進行修改以適應。 –