2016-07-28 6 views
-2

輸送業界では、規制によりサービス時間が制限されます。開始および終了フィールドを含む連続したdatetimeレコードを検索するmysqlクエリ

IはTask_ID呼ばAUTO_INCREMENTフィールド、User_IDと呼ばれる外部キーを有する整数フィールド、および2つの日時フィールド、Start_DT、及びEnd_DT有するテーブルを含むMySQLデータベースを持っています。

表:複数のタスクを含めることができ

Task_ID | User_ID | Start_DT | End_DT 

従業員のシフトは、各レコードを作成します。

従業員(User_ID)によって最新のエンドタイムを識別するクエリが既にあります。 (htmlユーザーインターフェースは、開始時刻が終了時刻より遅いデータ入力を防ぎます。)

(従業員によって)最新のエンドタイムに隣接するすべてのレコードを返すクエリを作成する必要があります。つまり、現在のレコードの開始時刻が前のレコードの終了時刻(従業員別)と等しいすべてのレコード。一連のタスク(レコード)の数はさまざまです。

連続する一連のタスクがタスクの数を超えないように十分なサブクエリをネストする必要がありますか、ギャップを探してそのギャップより後ですべてのレコードを返す方法がありますか?

単一のフィールドにギャップを見つけるためのアドバイスがたくさんありますが、私の検索ではこの質問にはあまり適していません。

(:)

1以下のイチゴのコメントへの対応)

CREATE TABLE `hoursofservice` (
    `Task_ID` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT, 
    `User_ID` SMALLINT(5) UNSIGNED NOT NULL, 
    `Location` VARCHAR(20) NULL DEFAULT NULL, 
    `Task` VARCHAR(30) NULL DEFAULT NULL, 
    `Start_DT` DATETIME NOT NULL, 
    `End_DT` DATETIME NULL DEFAULT NULL, 
    `Comment_1` VARCHAR(20) NULL DEFAULT NULL, 
    `Comment_2` VARCHAR(256) NULL DEFAULT NULL, 
    `Bad_Data` BIT(1) NOT NULL DEFAULT b'0', 
    PRIMARY KEY (`Task_ID`), 
    UNIQUE INDEX `Task_ID` (`Task_ID`), 
    INDEX `FK_hoursofservice_employee_id` (`User_ID`), 
    CONSTRAINT `FK_hoursofservice_employee_id` FOREIGN KEY (`User_ID`) REFERENCES `employee_id` (`User_ID`) ON UPDATE CASCADE 

と...

INSERT INTO hoursofservice (User_ID, Location, Task, Start_DT, End_DT, Comment_1, Comment_2) 
SELECT User_ID, Location, Task, Start_DT, End_DT, Comment_1, Comment_2 FROM read_text_file; 

2)結果セットは、そのテーブルから選択されたレコードになります最新のレコードからの開始時刻は前の時刻からの終了時刻と同じになり、同様に条件を満たすレコードがなくなるまで続きます。 (これらは、USER_IDが発注されます。)このような

+0

あなたが好きな場合は、アクションのこの単純な二段階のコース、次の考慮:あなたはまだ行っていない場合は1をしたがって、問題をより簡単に複製できるように、適切なCREATEおよびINSERT文(および/またはsqlfiddle)を提供してください。 2.まだ実行していない場合は、手順1で提供された情報に対応する結果セットを提供してください。 – Strawberry

+0

コーチングに感謝します。私はプロトコルの初心者です。 – dirk

+0

私たちに教えてください。私たちに見せてください! – Strawberry

答えて

0

何かがあなたのために働くかもしれない:

SELECT islands.[all relevant fields from "theTable"] 
FROM (
    SELECT [all relevant fields from "theTable"] 
     , @i := CASE 
      WHEN @prevUserId <> User_ID THEN 1 -- Reset "island" counter for each user 
      WHEN @prevStart <> End_DT THEN @i + 1 -- Increment "island" counter when gaps found 
      ELSE @i -- Do not change "island" counter 
      END AS island 
     , @prevStart := Start_DT -- Remember this Start_DT value for the next row 
     , @prevUserId := User_ID -- Remember this User_ID value for the next row 
    FROM (
     SELECT t.* 
     FROM theTable AS t 
     WHERE End_DT < [known or "ceiling" End_DT] 
      AND [limiting condition (for speed), 
       something like Start_DT > [ceiling] - INTERVAL 3 DAY 
       ] 
     ORDER BY User_ID, End_DT DESC 
    ) AS candidates -- Insures rows are in appropriate order for use with session variables. 
        -- Allows us to treat the inclosing query somewhat like a loop. 
    , (SELECT @i := 0 
      , @prevStart := '9999-12-31 23:59:59' 
      , @prevUserId := -1 
    ) AS init -- Initializing session variables; 
       -- can actually be done in preceeding SET statements 
       -- if the connection is preserved between the SETs and the query. 
    ORDER BY User_ID, Start_DT 
) AS islands -- Data from "theTable" should now have appropriate "islands" calculated 
WHERE islands.island = 1 -- Only keep the first "island" for each user 
ORDER BY islands.User_ID, islands.Start_DT 
; 
+0

すぐにお返事いただき、ありがとうございました。上司は私を何かに頼っていましたので、今日まであなたの解決策を試す機会はありませんでした。私が使用するmysqlバージョンは5.3.3です。テーブルエイリアス "t"が好きではありませんでしたが、 "t"がテーブル名に置き換えられた場合に実行されます。残念ながら、連続したレコード間の最初のギャップではなく、最新のレコードを返します。何か案は? – dirk

+0

あなたが試したクエリを見ることなく、私の最初の推測は、 "theTable"のすべてのフィールドでグループ化しなかったでしょう...(ああ、おそらく 't'が気に入らなかった理由は、その方法で外側のクエリで使用されていることを示しています)。 1行目の 't。* 'は、文字通り' t。*'ではなく、theTableのすべてのフィールドを示すためのものです。今私はそれについて考えているので、私は通常これを行うときにGROUP BYまたはHAVINGを使用しないので、おそらく別の層のクウェリングが必要なので、編集を行います。 – Uueerdo

+0

3行目と12行目のSELECT文は、13行目に示すエイリアスを使用していますか?私はt [fieldname]、[fieldname]、[tablename]。[fieldname]、[fieldname]を試してみましたが、これらを個別にバックティックで囲みてみました。すべてのバリエーションが "SQLエラー(1054)不明な列t。[fieldname]フィールドの一覧に戻ります"何か案は? – dirk

関連する問題