1

MySQL データベースで予定間の最初の 10 個の空の時間枠を選択しようとしています。

アポイント テーブルには、基本的に 3 つのフィールドがあります。

このようなデータを想像することができます (簡単にするために、datetime から日付部分を省略したので、これらの時間が同じ日にあると考えてみましょう)。また、データは startDateTime で並べ替えられます。

4 | 09:15:00 | 09:30:00
5 | 09:30:00 | 09:45:00
8 | 10:00:00 | 10:15:00
3 | 10:30:00 | 10:45:00
7 | 10:45:00 | 11:00:00
2 | 11:00:00 | 11:15:00
1 | 11:30:00 | 12:00:00

だから私の目標は抽出することです:

00:00:00 | 09:15:00
09:45:00 | 10:00:00
10:15:00 | 10:30:00
11:15:00 | 11:30:00

最終的にこれを行うことになりました:

SET @myStart = '2012-10-01 09:15:00';
SET @myEnd = NULL;
SET @prevEnd = NULL;
SELECT a.endDateTime, b.startDateTime, @myStart := a.endDateTime
FROM appointment a, appointment b, (
    SELECT @myEnd := min(c.startDateTime) 
    FROM appointment c 
    WHERE c.startDateTime >= @myStart
    ORDER BY startDateTime ASC
) as var , 
(SELECT @prevEnd := NULL) v
WHERE a.appointment_id = (
    SELECT appointment_id 
    FROM (
        SELECT appointment_id, max(endDateTime), @prevEnd := endDateTime 
        FROM appointment d
        WHERE (@prevEnd IS NULL OR @prevEnd = d.startDateTime) 
            AND d.startDateTime >= @myEnd
    ) as z
) 
    AND b.startDateTime > a.endDateTime 
ORDER BY b.startDateTime ASC LIMIT 0,10;

これは結果を返しません。ユーザー定義変数の初期化が正しくないためだと思います(それらを発見したばかりで、完全に間違って使用している可能性があります)。

@myStart の後の最初の予定で @myEnd を初期化することを目標とする最初のサブクエリのみを実行すると、実際には 09:15:00 が返されることがわかります。

2 番目のサブクエリ(SELECT @prevEnd := NULL) vは、メイン クエリで行が選択されるたびに @prevEnd を NULL に戻すことを意図しています。そのように機能するかどうかはよくわかりません...

最後のサブクエリは、null の @prevEnd と初期化された @myEnd で始まり、その後にギャップがある予定を選択することを意味します。クエリの残りの部分から分離されていれば、それも機能することを確認できました。

クエリを修正するために私ができること、そうでなければどのようにできる/すべきか、またはそれが可能かどうかについて何かアドバイスはありますか?

よろしくお願いします。

編集:次のように編集しました:

SELECT * 
    FROM (
        SELECT COALESCE( s1.endDateTime,  '0000-00-00 00:00:00' ) AS myStart, MIN( s2.startDateTime ) AS minSucc
        FROM appointment s1
        RIGHT JOIN appointment s2 ON s1.endDateTime < s2.startDateTime
            AND s1.radiologyroom_id = s2.radiologyroom_id
        WHERE s1.startDateTime >=  '2012-10-01 00:00:00'
            AND s1.radiologyroom_id =174
            AND s1.endDateTime <  '2013-01-01 00:00:00'
        GROUP BY myStart
        ORDER BY s1.startDateTime
    )s
WHERE NOT 
    EXISTS (
        SELECT NULL 
        FROM appointment
        WHERE startDateTime >= myStart
            AND endDateTime <= minSucc
            AND radiologyroom_id =174
        ORDER BY startDateTime
    )

6530 レコードから 14.6 秒で 369 行を取得します。

4

1 に答える 1

1

idsの間にギャップがなく、id常に増加している場合は、次を使用できます。

SELECT coalesce(s1.endDateTime, '0000-00-00 00:00:00'), s2.startDateTime
FROM
  slots s1 right join slots s2
  on s1.appointment_id=s2.appointment_id-1
WHERE coalesce(s1.endDateTime, '0000-00-00 00:00:00')<s2.startDateTime
LIMIT 10

編集:これを試すこともできます:

SELECT * FROM
  (SELECT
     coalesce(s1.endDateTime, '0000-00-00 00:00:00') as start,
     min(s2.startDateTime) minSucc
   from slots s1 right join slots s2
        on s1.endDateTime<s2.startDateTime
   group by start) s
WHERE
  not exists (select null
              from slots
              where startDateTime>=start
              and endDateTime<=minSucc)

EDIT2:私は変数を使ったクエリについてはあまり実用的ではないことを認めますが、これはうまくいくように見えます:

select d1, d2 from (
  select
    @previous_end as d1,
    s.startDateTime as d2,
    @previous_end:=s.endDateTime
  from (select startDateTime, endDateTime from slots order by startDateTime) s,
       (select @previous_end := '0000-00-00 00:00:00') t) s
where d1<d2
于 2012-12-11T11:47:44.100 に答える