2

MySQL には 5 つのテーブルがあり、そこからいくつかのレポートを生成しています。表示のためにテーブル名を少し抽象化します。私が作業しているテーブルが以下のとおりであると仮定しましょう:

History  (id, serial, date, time) : Stores historic data, this is the main
                                    column we query.
Serial   (id, serial)             : Stores serial numbers used in the next
                                    3 tables.
Employee (id, serial_id, name)
Event    (id, serial_id, name)
Location (id, serial_id, name)

編集:より明確で理解しやすいことを期待して、質問全体を書き直しました...

イベントをクエリする必要があります。また、従業員のシリアルがイベントに一致するシリアルの行の直前に履歴で見つかっ場合、その従業員はそのイベントに関連付けられます。イベントに一致するシリアルを含む行で、その場所がそのイベントに関連付けられます。

サンプルデータ:

History:
+------+------------+------------+----------+
| id   | serial     | date       | time     |
+------+------------+------------+----------+
| 1    | 00001234   | 2012-09-25 | 09:00:00 |
+------+------------+------------+----------+
| 2    | 00001235   | 2012-09-25 | 09:01:00 |
+------+------------+------------+----------+
| 3    | 00001236   | 2012-09-25 | 09:02:00 |
+------+------------+------------+----------+
| 4    | 00001235   | 2012-09-25 | 09:05:00 |
+------+------------+------------+----------+
| 5    | 00001236   | 2012-09-25 | 09:07:00 |
+------+------------+------------+----------+
| 6    | 00001235   | 2012-09-25 | 09:10:00 |
+------+------------+------------+----------+
| 7    | 00001235   | 2012-09-25 | 09:11:00 |
+------+------------+------------+----------+
| 8    | 00001235   | 2012-09-25 | 09:12:00 |
+------+------------+------------+----------+
| 9    | 00001236   | 2012-09-25 | 09:15:00 |
+------+------------+------------+----------+
| 10   | 00001234   | 2012-09-25 | 09:20:00 |
+------+------------+------------+----------+
| 11   | 00001236   | 2012-09-25 | 09:25:00 |
+------+------------+------------+----------+

Serial:
+----------+------------+
| id       | serial     |
+----------+------------+
| 1        | 00001234   |
+----------+------------+
| 2        | 00001235   |
+----------+------------+
| 3        | 00001236   |
+----------+------------+

Employee:
+----------+------------+-------------+
| id       | serial_id  | name        |
+----------+------------+-------------+
| 1        | 1          | John Smith  |
+----------+------------+-------------+

Event:
+----------+------------+-------------+
| id       | serial_id  | name        |
+----------+------------+-------------+
| 1        | 2          | Event 1     |
+----------+------------+-------------+

Location:
+----------+------------+-------------+
| id       | serial_id  | name        |
+----------+------------+-------------+
| 1        | 3          | Location 1  |
+----------+------------+-------------+

通常の LEFT JOIN クエリを実行した場合 (結果の違いを明確にするため)、次のクエリを使用すると、結果は次のようになります。

SELECT
    history.id,
    history.serial,
    history.date,
    history.time,
    employee.name as 'employee',
    event.name as 'event',
    location.name as 'location'
FROM history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN employee ON serial.id = employee.serial_id
LEFT JOIN event ON serial.id = event.serial_id
LEFT JOIN location ON location.id = location.serial_id
ORDER BY date, time

通常の LEFT JOIN の結果は次のとおりです (わかりやすくするためだけに、この結果セットは必要ありません)。

+----+----------+------------+----------+------------+----------+------------+
| id | serial   | date       | time     | employee   | event    | location   |
+----+----------+------------+----------+------------+----------+------------+
| 1  | 00001234 | 2012-09-25 | 09:00:00 | John Smith | NULL     | NULL       |
+----+----------+------------+----------+------------+----------+------------+
| 2  | 00001235 | 2012-09-25 | 09:01:00 | NULL       | Event 1  | NULL       |
+----+----------+------------+----------+------------+----------+------------+
| 3  | 00001236 | 2012-09-25 | 09:02:00 | NULL       | NULL     | Location 1 |
+----+----------+------------+----------+------------+----------+------------+
| 4  | 00001235 | 2012-09-25 | 09:05:00 | NULL       | Event 1  | NULL       |
+----+----------+------------+----------+------------+----------+------------+
| 5  | 00001236 | 2012-09-25 | 09:07:00 | NULL       | NULL     | Location 1 |
+----+----------+------------+----------+------------+----------+------------+
| 6  | 00001235 | 2012-09-25 | 09:10:00 | NULL       | Event 1  | NULL       |
+----+----------+------------+----------+------------+----------+------------+
| 7  | 00001235 | 2012-09-25 | 09:11:00 | NULL       | Event 1  | NULL       |
+----+----------+------------+----------+------------+----------+------------+
| 8  | 00001235 | 2012-09-25 | 09:12:00 | NULL       | Event 1  | NULL       |
+----+----------+------------+----------+------------+----------+------------+
| 9  | 00001236 | 2012-09-25 | 09:15:00 | NULL       | NULL     | Location 1 |
+-----+---------+------------+----------+------------+----------+------------+
| 10 | 00001234 | 2012-09-25 | 09:20:00 | John Smith | NULL     | NULL       |
+----+----------+------------+----------+------------+----------+------------+
| 11 | 00001236 | 2012-09-25 | 09:25:00 | NULL       | NULL     | Location 1 |
+----+----------+------------+----------+------------+----------+------------+

クエリはイベントに基づいている必要があり、イベントは決して NULL であってはなりません。行PRIORを見て、それを従業員 (または一致しない場合は null) としてラベル付けする必要があります。行AFTERを見て、場所 (または一致しない場合は null) としてラベル付けする必要があります。上記のデータを使用した結果の例:

Result should be:
+----------+------------+------------+------------+----------+------------+
| e_serial | date       | time       | employee   | event    | location   |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:01:00   | John Smith | Event 1  | Location 1 |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:05:00   | NULL       | Event 1  | Location 1 |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:10:00   | NULL       | Event 1  | NULL       |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:11:00   | NULL       | Event 1  | NULL       |
+----------+------------+------------+------------+----------+------------+
| 00001235 | 2012-09-25 | 09:12:00   | NULL       | Event 1  | Location 1 |
+----------+------------+------------+------------+----------+------------+

これが一連のサブ選択などで可能かどうかはわかりませんが、これはSQLで私のリーグをはるかに超えていると思います。現在、私はこれをアプリケーション ロジックで使用していますが、SQL のみで処理する方がクリーンで高速であると考えています。

どんな助けでも素晴らしいでしょう。

4

2 に答える 2

2
SELECT serial_id AS `serial`,
(SELECT `date` FROM History WHERE serial_id= event2.serial_id ) AS `date`,
(SELECT `time` FROM History WHERE serial_id= event2.serial_id ) AS `time`,
(SELECT `name` FROM event1 WHERE serial_id= event2.serial_id ) AS `event1`,`name` AS event2,
(SELECT `name` FROM event3 WHERE serial_id= event2.serial_id ) AS `event1`
FROM event2

histroyテーブルは、である必要があり、の代わりにHistory (id, serial_id, date, time)含まれている必要がありますserial_idserial name

あなたのシナリオの希望のためにそれがうまくいくように

SELECT serial_id AS `serial`,
(SELECT `date` FROM History WHERE `serial` = (SELECT `serial` FROM `serial` WHERE id = event2.serial_id LIMIT 0,1)) AS `date`,
(SELECT `time` FROM History WHERE `serial`= (SELECT `serial` FROM `serial` WHERE id = event2.serial_id LIMIT 0,1)) AS `time`,
(SELECT `name` FROM event1 WHERE serial_id= event2.serial_id ) AS `event1`,
`name` AS event2,
(SELECT `name` FROM event3 WHERE serial_id= event2.serial_id ) AS `event1`
FROM event2
于 2012-09-25T05:28:58.193 に答える
2

他の誰かが問題に遭遇した場合に備えて、ここに解決策を投稿してください。私を正しい方向に導いてくれたdianujに感謝します。

SELECT
    serial.serial as 'e_serial',
    @dt:=TIMESTAMP(history.date, history.time) as 'date_time',
    history.date,
    history.time,
    (SELECT
        employee.name
    FROM
        history
        LEFT JOIN serial ON history.serial = serial.serial
        LEFT JOIN employee ON employee.serial_id = serial.id
    WHERE
        TIMESTAMP(history.date, history.time) = (
            SELECT
                max(TIMESTAMP(history.date, history.time))
            FROM
                history
            WHERE TIMESTAMP(history.date, history.time) < @dt
        )
    ) as 'employee',
    event.name as 'event',
    (SELECT
        location.name
    FROM
        history
        LEFT JOIN serial ON history.serial = serial.serial
        LEFT JOIN location ON location.serial_id = serial.id
    WHERE
        TIMESTAMP(history.date, history.time) > @dt
    LIMIT 1
    ) as 'location'
FROM history
LEFT JOIN serial ON history.serial = serial.serial
LEFT JOIN event ON serial.id = event.serial_id
WHERE event.name IS NOT NULL
ORDER BY history.date, history.time

そして結果

+----------+---------------------+------------+----------+------------+---------+------------+
| e_serial | date_time           | date       | time     | employee   | event   | location   |
+----------+---------------------+------------+----------+------------+---------+------------+
| 00001235 | 2012-09-25 09:01:00 | 2012-09-25 | 09:01:00 | John Smith | Event 1 | Location 1 |
| 00001235 | 2012-09-25 09:05:00 | 2012-09-25 | 09:05:00 | NULL       | Event 1 | Location 1 |
| 00001235 | 2012-09-25 09:10:00 | 2012-09-25 | 09:10:00 | NULL       | Event 1 | NULL       |
| 00001235 | 2012-09-25 09:11:00 | 2012-09-25 | 09:11:00 | NULL       | Event 1 | NULL       |
| 00001235 | 2012-09-25 09:12:00 | 2012-09-25 | 09:12:00 | NULL       | Event 1 | Location 1 |
+----------+---------------------+------------+----------+------------+---------+------------+
5 rows in set (0.01 sec)
于 2012-09-26T01:12:56.353 に答える