1

私はこれに数日間取り組んできましたが、理解できません。あなたが私を助けてくれることを願っています。

予約制に取り組んでいますが、日時にテーブルが空いているか確認したいのですが。これが私のデータベースの様子です。

ここに画像の説明を入力してください

利用可能なテーブルを選択ドロップダウンメニューに入れたいので、Webサイトでは利用可能なテーブルのみが表示されます。

次のクエリを使用すると、予約テーブルを取得できます

SELECT res.reserveringsnr, datum, begintijd, eindtijd, tafr.tafelnr FROM reserveringen AS res
INNER JOIN tafels_regel AS tafr
ON res.reserveringsnr = tafr.reserveringsnr
WHERE (res.datum = "2013/12/18" AND (res.begintijd BETWEEN "12:00:00" and "14:00:00"))

そのため、そのクエリは予約テーブルを出力しますが、ここで行き詰まります。特定のテーブルがDATEとTIMEに予約されているかどうかを確認する方法がわかりません。

(注:日付と時刻は変数で入力されますが、この例ではテキストのみを使用しました)

編集:@sebt彼のソリューションに取り組んでいます

まず第一に、あなたの質問に答えるために

  1. 予約は常に同じ日になります
  2. 予約の時間は決まっており、常に2時間です。

私はsebtのクエリを私の値に編集しました:

    SELECT t.* FROM
    tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          tafels_regel tf
    INNER JOIN
          reserveringen res
    ON tf.reserveringsnr=res.reserveringsnr
    WHERE
    res.datum="2012/01/12" AND
    res.begintijd<"19:00:00" AND
    res.eindtijd>"21:00:00" 
    )
ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTime.tafelnr
WHERE ReservationsAtThisTime.tafelnr IS NULL

このクエリ出力は次の結果です ここに画像の説明を入力してください

ご覧のとおり、クエリ結果にはすべてのテーブルが表示されます(12)。

また、reserveringen、tafels_regel、およびtafelsテーブルを.csvにエクスポートしました(以下の編集済み.csvを参照)。

編集2:

クエリをもう一度編集しました。一部で機能します。これはクエリです(スクリーンショット

    SELECT t.* FROM
    tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          tafels_regel tf
    INNER JOIN
          reserveringen res
    ON tf.reserveringsnr=res.reserveringsnr
    WHERE
    res.datum="2013/01/12" AND
    res.begintijd <= "19:00:00" AND
    res.eindtijd >= "21:00:00" 
    )
ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTime.tafelnr
WHERE ReservationsAtThisTime.tafelnr IS NULL

2013/01/12には2件の予約があります。(編集済みの.csvをダウンロード)

予約1:タフェル1で19:00から21:00まで

予約2:tafel11とtafel12の20:00から22:00まで

上記のクエリを実行すると、tafel1は19:00から21:00まで予約されているため、表示されていないtafelはtafel1だけです。ただし、20:00から22:00まではtafel11と12も予約されています。

クエリ結果からわかるように、tafel1のみが予約されています。しかし、19:00から21:00まで別の予約を行い、利用可能なタフェルをチェックしていると、タフェル11とタフェル12が引き続き表示されます。

タフェルは19:00に無料になりますが、私たちはいつも2時間座っているので、そこに座ることはできません。

ご入力いただきありがとうございます@sebt、このクエリでさらに私を助けてくれることを願っています!

問題が解決しました

すべての助けをありがとう、これは最後のクエリです

SELECT t.* FROM
    tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          tafels_regel tf
    INNER JOIN
          reserveringen res
    ON tf.reserveringsnr=res.reserveringsnr
    WHERE
    res.datum="2013/01/12" AND
    res.eindtijd > "19:00:00" AND
    res.begintijd < "21:00:00" 
    )
ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTime.tafelnr
WHERE ReservationsAtThisTime.tafelnr IS NULL
4

2 に答える 2

1

SQLの「テーブル」(データベーステーブル)とデータベース内のオブジェクトの1つ(おそらく)オランダ語で「tafel」と呼ばれるレストランテーブルとの間のあいまいさのために、あなたの質問は少し紛らわしい言い方をしていると思います。 ?

(あいまいさを取り除くため、それらを「tafel」と呼び続けましょう)

予約されていないタフェルのみを選択するには、すべてのタフェルを[希望の時間]に現在の予約のセットに左結合し、そのような予約がないタフェルのみを返すことができます。

SELECT t.* FROM
    Tafels t
LEFT JOIN
    (SELECT tafelnr FROM
          Tafels_regel tf
    INNER JOIN
          Reserveringen res
    ON tf.reserveringnr=res.reserveringnr
    WHERE
    res.Datum=[desired date] AND
    res.begintijd<[desired time] AND
    res.eindtijd>[desired time]
    ) ReservationsAtThisTime
ON t.tafelnr=ReservationsAtThisTIme.tafelnr
WHERE ReservationsAtThisTime.tafelNR IS NULL

これには、おそらくまだいくつかの調整が必要です。

  1. 数日間にわたる予約(つまり、ある日を見つめて別の日に終了する)は適切に処理されません。(しかし、多分あなたはこれを必要としないでしょう)
  2. テーブルは、たとえば10/01/2012 12:30に利用可能として表示されますが、実際には10/01/2012 12:45から予約されています(おそらく、少なくとも無料ではないテーブルには誰も興味がありません)。 X分-1時間?-希望する開始時間の後?)。

編集(以下のOPのコメントに答えるために):

データを見ると、2013年12月1日の19:00から21:00までTafel1が予約されていることがわかります。期待した結果が得られない理由がわかります(つまり、Tafel 1は無料ではないため、表示しないでください)。

  1. クエリで使用している日付は、2013年ではなく2012年です(これは、おそらく私の例で、2012年を使用した場合に発生しました)
  2. 私は、単一の特定の時点の「望ましい時間」を使用するように例を設計しました。私の考えでは、「希望の時間」はポイント(19:30など)になるため、19:00から20:00までの予約では、この希望の時間が利用できなくなります。使用している「希望時間」は範囲(19:00〜21:00)であり、予約の範囲とまったく同じであるため、クエリの「<」と「>」は次のようになります。 「希望の時間」と競合するため、この予約を取得できませんでした(代わりに、「<="および"> = "で修正されます)。

ただし、すべての予約は2時間であるとおっしゃっていたので、次のように、希望の開始時刻を使用して「競合する予約」を指定する方が簡単です。「競合する予約」とは、希望の開始時間:

a。res.Datum=[希望日]; およびb。res.eindtijd>[希望の開始時間]; およびc。res.begintijd<[希望の開始時間+2時間]

2時間を追加するためにコードがどのように機能するかは完全にはわかりません(私の専門はMySQLではなくMS-SQLであり、日付/時刻の操作はSQLのバージョンに少し固有である可能性があります)。

EDIT2(OPの再編集された質問への回答):

わかりやすくするために、次の用語を定義します。

既存の予約:データベースにすでに存在します。TafelNr、Date、StartTime(begintijd)、EndTime(eindtijd)があります

提案された予約:ユーザーが作成したい予約-当然、データベースにまだ存在していないか、TafelNrがあります。日付、開始時刻、終了時刻があります。

(提案された予約に対してStartTimeとEndTimeの両方を使用してクエリを実装しました。StartTimeを使用してから[StartTime + 2時間]を使用することをお勧めします。ただし、これらのどちらを使用しても違いはありません。私たちが話している質問)

クエリが正しく機能していれば、tafels11と12は表示されないはずです。19:00から21:00までの提案された予約は、20:00から22:00までの既存の予約と競合するはずです。しかし、ご存知のように、この競合は本来のように検出されません。

その理由は、開始時間と終了時間の比較が少し間違っているためです。あなたがそれをコーディングした方法:

res.begintijd <= [Proposed Start time] AND
res.eindtijd >= [Proposed End time]

提案された予約にまたがる場合にのみ、既存の予約が競合していることがわかります。つまり、正確に同じ時刻に入力されるか、提案された予約の前および/または後に延長されます。

隣接する線に沿ってスライドするレゴの平行ブロックのような2つの予約(既存および提案)を想像すると便利です。彼らはまったく連絡をとることができません(良い)。または単に連絡を取ります(一方の終了=もう一方の開始:良い、競合なし-ちょうど!); または、一方の終わりがもう一方の始まりよりも長くなる可能性があります(競合)。または、一方が他方にまたがることができ、同時にまたは他方の前に開始し、他方と同時にまたは後で終了します(競合)。

これは、私が何年も前に予約システムを使って作業してきたトリックです。競合を見つけるための正しい比較(上記の以前の編集のように)は次のとおりです。

ExistingBookingEndTime>ProposedBookingStartTime AND
ExistingBOokingStartTime<ProposedBookingEndTime

または、オブジェクト名を使用します。

res.eindtijd>"19:00:00" AND
res.begintijd<"21:00:00"

これは最初は意味がないかもしれませんが、レゴブロックについて考えると意味があります。

注意

1. <=と>=ではなく<と>を使用しています。これは、予約が重複しない限り、予約が互いに直接拡張して「タッチ」できると想定しているためです。

2.日付と時刻を比較するときは注意してください。数字や文字列であるかのように比較するだけで、奇妙な結果が得られる可能性があります。MySQLがこれをどのように処理するかはわかりませんが、常に注意を払っています。

于 2013-01-09T14:09:17.347 に答える
0

ええと、私はあなたのデータベース構造を本当に理解していません。しかし、あなたを軌道に乗せるために:

  1. すべてのテーブルをクエリするだけです
  2. 結果セットから反転テーブルを除外します

何かのようなもの:

SELECT tafelnaam FROM Tafels WHERE tafelnr NOT IN (SELECT tafelnr *OF YOUR RESEVED TABLES*)
于 2013-01-09T13:38:23.797 に答える