2010-12-13 12 views
2

私は、あなたがログインしている時間を記録するゲームに取り組んでいます。それは、データベースにチェックイン時間とチェックアウト日を保存します。アドバンストSQLの日付の差し引き

これは、フラグをキャプチャするようなもので、スコアが18:00(午後6時)から午前9:00(午前9時)までの時間を数えるだけです。これは毎日、そして一度だけではありません。

スコアは秒単位で表示されます。簡単に言えば、チェックインとチェックアウトの時間の差(毎日18:00〜09:00の時間を差し引いた時間)。

誰かが高度なSQLの日付計算の熟練者であり、私を助けることができますか?お願いします!

これは、時間減算せずに、私の基本的なクエリです:

SELECT 
SUM(TIMESTAMPDIFF(SECOND,sessions.checkin,IFNULL(sessions.checkout,NOW()))) 
AS score 
FROM `sessions` 
GROUP BY `user_id` 
+0

これは完全にMySQLでなければならないのですか、それともプログラミング言語で行うことはできますか?それは非常に複雑なクエリのように聞こえる。 – Danosaure

+0

もしあなたが好きなのであれば、phpで行うこともできます。 それはうまくいくでしょうか?18:00と09:00の差を計算し、それを掛けた日数を掛けます。 – sparkle

答えて

1

それは(あなたはこれをたくさんやろうとしている場合、クエリの読みやすさのためにfunctionsを追加したい場合があります)きれいではありません

あなたが複数日にまたがるログインがまたはpする場合、それは動作しません

SELECT 
     user_id, 
     SUM(
      TIMESTAMPDIFF(SECOND, 
      CASE 
       WHEN sessions.checkin < timestamp(date(sessions.checkin), maketime(9,0,0)) 
        THEN timestamp(date(sessions.checkin), maketime(9,0,0)) 
       WHEN sessions.checkin > timestamp(date(sessions.checkin), maketime(18,0,0)) 
        THEN timestamp(date(sessions.checkin)+1, maketime(9,0,0)) 
       ELSE 
        sessions.checkin 
      END, 
      CASE 
       WHEN IFNULL(sessions.checkout, now()) > timestamp(date(IFNULL(sessions.checkout, now())), maketime(18,0,0)) 
        THEN timestamp(date(IFNULL(sessions.checkout, now())), maketime(18,0,0)) 
       WHEN IFNULL(sessions.checkout, now()) < timestamp(date(IFNULL(sessions.checkout, now())), maketime(9,0,0)) 
        THEN timestamp(date(IFNULL(sessions.checkout, now()))-1, maketime(18,0,0)) 
       ELSE 
        IFNULL(sessions.checkout, now()) 
      END)) AS score 
    FROM `sessions` 
    GROUP BY `user_id` 

次を行うことができます複数日にまたがるログインしていないと仮定すると、 1日目の18時05分にチェックインし、3日目の8時55分にチェックアウトするなど、複数の日にまたがるログインで動作することができますが、複数の日にカウント可能な時間に達するとすぐに、複数の日にカウント可能な時間にまたがるレコードごとに、結果から無制限の秒数を差し引く必要があります。もしあなたがそれに助けが必要なら私に教えてください。

上記のクエリは、比較的安価で実行する必要があります -とにかくあなたがテーブル全体上でそれを実行しているという事実を考えると、それはテーブルスキャンを行います、繰り返し計算が多いという事実と、それが見えること巨大なものはそれほど重要ではありません。これらの計算は追加のI/Oなしでメモリ内で実行され、ディスクI/Oよりも数桁高速です(元のクエリの実行時間と比較して、パフォーマンスが低下するかどうかをお知らせください)。

+0

私はあなたが私に提供したスクリプトでいくつか修正を加えました。ありがとう。私は言う必要があります、これは大きなクエリの単なるサブクエリでした。今は巨大です。笑。しかしそれは問題ではありません! – sparkle