2017-01-24 7 views
1

私は、TIMESTAMP列 'Start'とTIMESTAMP列 'End'を持つMYSQL表を持っています。開始から終了までの分数を返したい(終了は常に開始より後)。通常私は 'TIMESTAMPDIFF()'を使用しますが、今回は午前9時から午後22時まで、その日の各日の分を取得する必要があります。指定された時間範囲の2つの日付間の経過時間

行に開始 '2017-01-01 07:15:00'と終了 '2017-01-02 11:30:00'がある場合、経過時間は15.5時間(930分) 。

私はこれを行うためのまともな方法を思いつくのに苦労しています。私の検索しているオンラインでは、私が探しているものはまったく見つかりませんでした。誰かが私を助けてくれる?

編集:私はこの思い付いた

CREATE TABLE date_ranges (
Start TIMESTAMP, 
End TIMESTAMP 
); 

INSERT INTO date_ranges VALUES('2017-01-01 07:15:00','2017-01-02 11:30:00'); 

SELECT Start, End, TIMESTAMPDIFF(MINUTE, Start, End) AS MinutesElapsed 
FROM date_ranges; 

私は分単位で時間を指定した時間帯にのみ計算された部分が欠落しています(午前9時22pmまで) 。何か案は?ここで

+1

たプログラミング言語、あなたが使っていますか? – Rashad

+0

良い質問... – dadde

+0

データベースにカレンダーテーブルがありますか? –

答えて

0

あなたが行く:

SELECT t1, t2, (TIMESTAMPDIFF(MINUTE, t1, t2) - TIMESTAMPDIFF(DAY, t1, t2)*660) FROM 

(SELECT CASE WHEN t1 < STR_TO_DATE(concat(date_format(t1, '%Y-%m-%d'), ' 09:00:00'), '%Y-%m-%d %h:%i:%s') 
THEN STR_TO_DATE(concat(date_format(t1, '%Y-%m-%d'), ' 09:00:00'), '%Y-%m-%d %h:%i:%s') 
ELSE t1 
END AS t1 FROM test) test1, 

(SELECT CASE WHEN t2 > STR_TO_DATE(concat(date_format(t2, '%Y-%m-%d'), ' 22:00:00'), '%Y-%m-%d %h:%i:%s') 
THEN STR_TO_DATE(concat(date_format(t2, '%Y-%m-%d'), ' 22:00:00'), '%Y-%m-%d %h:%i:%s') 
ELSE t2 
END AS t2 FROM test) test2; 

660 =午後10時と午前9時00分の間(11時間)

の数はここSQL Fiddleです。

+0

09:00〜22:00の間の分数は実際には780(13 * 60)です。 –

0

それは非常に簡潔ではないのですが、これはあなたが望む結果を与える必要があります年の指定した数の日付と

select started_at,ended_at, 
    (case 
    when date(ended_at) = date(started_at) 
    then 
    timestampdiff(
     minute, 
     greatest(started_at,concat(date(started_at),' 09:00:00')), 
     least(ended_at,concat(date(ended_at),' 22:00:00')) 
    ) 
    else 
    timestampdiff(
     minute, 
     least(greatest(started_at,concat(date(started_at),' 09:00:00')),concat(date(started_at),' 22:00:00')), 
     concat(date(started_at),' 22:00:00') 
    ) 
    + 
    timestampdiff(
     minute, 
     concat(date(ended_at),' 09:00:00'), 
     greatest(least(ended_at,concat(date(ended_at),' 22:00:00')),concat(date(ended_at),' 09:00:00')) 
    )  
    + ((datediff(ended_at,started_at)-1)*780) 
    end) as total_minutes 
from your_table; 
0
--Generating all dates in 2017. 

CREATE TABLE CALENDAR AS --Use a different table name if CALENDAR already exists 
SELECT '2017-12-31 09:00:00' - INTERVAL c.number DAY AS start_datetime,'2017-12-31 22:00:00' - INTERVAL c.number DAY AS end_datetime 
FROM (SELECT singles + tens + hundreds number FROM 
(SELECT 0 singles 
UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) singles JOIN 
(SELECT 0 tens 
UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30 
UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60 
UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90 
) tens JOIN 
(SELECT 0 hundreds 
UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300 
UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600 
UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900 
) hundreds 
ORDER BY number DESC) c 
WHERE c.number BETWEEN 0 and 364 
; 
--End of table creation 

--Actual query begins here 
SELECT D.`START`, 
     D.`END`, 
     SUM(TIMESTAMPDIFF(MINUTE,GREATEST(D.`START`,C.START_DATETIME), LEAST(D.`END`,C.END_DATETIME))) AS TOTAL_TIME 
FROM CALENDAR C 
LEFT JOIN DATE_RANGES D ON DATE(C.START_DATETIME) >= DATE(D.`START`) 
AND DATE(C.START_DATETIME) <= DATE(D.`END`) 
WHERE D.`START` IS NOT NULL 
    AND D.`END` IS NOT NULL 
GROUP BY D.`START`, 
     D.`END` 
; 
  • Construct a calendar table。各日付は、開始時刻が09:00、終了時刻が22:00です。
  • このテーブルに結合を残して、日付範囲テーブルから日付ごとに1行を取得します。
  • 毎日の差を合計して、合計作業時間を取得します。

Sample Demo

0
Day 1   Day 2  Day 3 
|--********--|--********--|--********--| 
    |__________________________| 

質問は、私見では初日どのように多くの分を知ることであり、何分最終日、中間日は780分を持っています。

中間計算に役立つサブクエリを使用しました。

select 
    if(hour(t1) < 9, date(t1) + interval 9 hour , t1) as tIni1, 
    date(t1) + interval 22 hour as tFin1, 
    date(t2) + interval 9 hour as tIni2, 
    if(hour(t2) > 22, date(t2) + interval 22 hour, t2) as tFin2, 
    TIMESTAMPDIFF(day, date(t1), date(t2)) numDays 
from 
    tdt 

tIni1とtFin1は、最初の日の期間であり、そしてtIni2、tFin2最終日の期間は、明らかに最初と最後の日を同じにすることができます。

次に、中間日ごとに、第1日の分+第2日の分+ 780分を計算します。

select numDays, tIni1, tFin1, tIni2, tFin2, 
    if (numDays = 0, 
     TIMESTAMPDIFF(minute, tIni1, tFin2), 
      TIMESTAMPDIFF(minute, tIni1, tFin1) 
      + TIMESTAMPDIFF(minute, tIni2, tFin2) 
      + (numDays - 1) * 780 
     ) as Minutes 
from (
     select 
      if(hour(t1) < 9, date(t1) + interval 9 hour , t1) as tIni1, 
      date(t1) + interval 22 hour as tFin1, 
      date(t2) + interval 9 hour as tIni2, 
      if(hour(t2) > 22, date(t2) + interval 22 hour, t2) as tFin2, 
      TIMESTAMPDIFF(day, date(t1), date(t2)) numDays 
     from 
      tdt 
    ) ti 
; 

ここでそれを試してみてください。http://rextester.com/GDHAB78973

関連する問題