3

このSQLクエリに問題があるようです。

SELECT * FROM appts 
WHERE timeStart >='$timeStart' 
AND timeEnd <='$timeEnd' 
AND dayappt='$boatdate'

時間は軍事時間としてフォーマットされます。ロジスティクスでは、ボートのレンタルは午前7時から午後1時まで、または午前9時から午後1時まで、または午前9時から午後5時まで予約できます。その範囲内にapptがある場合、apptsを返す必要がありますが、一貫性がないことが証明されています。午前9時から午後1時までを選択すると、午前9時から午後1時まで重複していても、午前7時から始まったアプリは無視されます。9から5を選択すると、午前7時から午後1時の場合でも、何も返されません。重複するものを含め、timeStartからtimeEndまでの全範囲を含むSQLステートメントを作成するにはどうすればよいですか?

4

4 に答える 4

8

Shahkalpesh はこの質問に次のように答えました。

ORが必要だと思います。

SELECT * FROM appts 
WHERE (timeStart >='$timeStart' 
OR timeEnd <='$timeEnd')
AND dayappt='$boatdate'

これは間違っていると思うというコメントを投稿し、反例をいくつか示しました。

これは明らかに間違っています - @ShaneD は正しいです。たとえば、05:00 から 06:00 の間の予約が選択されます。これは、実際の終了時刻が、質問したどの終了時刻よりも短いためです。同様の理由で、18:00 以降のレンタルも受け取ります。

私のコメントへの返答として、Shahkalpesh は次のように要求しました。

予想される出力を含むデータと入力パラメーターを含む別の返信を投稿していただけますか?

十分に - はい。少し編集して、質問は次のように述べています。

ロジックは、ボートのレンタルを予約できるということです

  • 午前7時から午後1時まで、または
  • 午前9時から午後1時まで、または
  • 午前9時から午後5時まで。

その範囲内に予定がある場合、予定を返すはずですが、一貫性がないことが証明されています。午前 9 時から午後 1 時までを選択すると、...


背景は十分。予定の日付は無視して、時間だけを考慮してください。記録される時間を hh:mm 形式に制限する簡単な方法があると思います。すべての DBMS が実際にそれを提供しているわけではありませんが、hh:mm:ss を処理するための拡張機能は簡単です。

Appointments

Row     timeStart   timeEnd   Note
  1     07:00       13:00     First valid range
  2     09:00       13:00     Second valid range
  3     09:00       17:00     Third valid range
  4     14:00       17:00     First plausibly valid range
  5     05:00       06:00     First probably invalid range
  6     18:00       22:30     Second probably invalid range

09:00 ~ 13:00 の範囲で重複する予定を検索すると、Shahkalpesh の (単純化された) クエリは次のようになります。

SELECT * FROM Appointments
    WHERE (timeStart >= '09:00' OR timeEnd <= '13:00')

これにより、6 行すべてのデータが返されます。ただし、行 1、2、3 のみが 09:00 ~ 13:00 の時間帯と重複しています。行 1、2、および 3 が唯一の有効な代表的な予定値である場合、Shahkalpesh のクエリは正しい答えを生成します。ただし、行 4 (もっともらしいと思います) が許可されている場合は、返されるべきではありません。同様に、5 行目と 6 行目 (存在する場合) は返されません。[実際に timeStart <= timeEnd は、テーブル内のすべての行を想定すると (そして、混乱させる NULL 値はありません)、Shahkalpesh のクエリは 09:00-13:00 のクエリに対して任意の行のデータを返すことがわかります。行の時刻が 09:00 より大きいか、終了時刻が 13:00 未満であるか、またはその両方です。これは、WHERE 句での書き込み 1 = 1 またはその他のトートロジーと同じです。]

ShaneD のクエリを (簡略化して) 考えると、次のようになります。

SELECT * FROM Appointments
    WHERE timeStart <= '13:00' AND timeEnd >= '09:00'

行 1、2、および 3 も選択されていることがわかりますが、行 4 (timeStart > '13:00' のため)、5 (timeEnd < '09:00' のため)、および 6 (timeStart > '13 のため) は拒否されます。 00')。この式は、「重なり合う」行を選択する方法の典型的な例であり、「出会う」と「出会う」(たとえば、「アレンの間隔代数」を参照) を重なりとして数えます。「>=」および「<=」を変更すると、重複としてカウントされる間隔のセットが変更されます。

于 2008-12-30T08:40:09.750 に答える
6

正しいチェックは次のようになります。

SELECT * FROM appts 
WHERE timeStart <='$timeEnd' 
AND timeEnd >='$timeStart' 
AND dayappt='$boatdate'

他にも良い説明がありますが、これを自分で視覚化する方法についての別の説明で更新します。ほとんどの人は、2つの期間を考慮して、それぞれの可能な重複を探しています。彼らは、予定の重複を引き起こす可能性のある開始と終了の各組み合わせを考えようとしています。私はそれを、2つの期間が重ならない場合と考えています。これは、何らかの理由で私にとっては簡単です。

私がチェックしている期間が今日であるとすると、今日重複していない期間を見つけたいと思います。そのためのシナリオは実際には2つだけです。期間が今日の後に開始する(PeriodStart> EndOfToday)か、期間が今日の前に終了する(PeriodEnd <StartOfToday)かのいずれかです。

重複しないための簡単なテストがあるとすると、
(PeriodStart> EndOfToday)または(PeriodEnd <StartOfToday)

すばやくめくって、オーバーラップの簡単なテストを行います:
(PeriodStart <= EndOfToday)AND(PeriodEnd> = StartOfToday)

-シェーン

于 2008-12-30T05:18:28.360 に答える
0

Shane、Shahkalpesh、Jonathan に感謝します。

実際、Shane が変数を「交換」したという事実を見落としていました (timeStart <= $timeEnd である必要がある場合でも、timeStart<=$timeStart を使用していました)。ジョナサン/シェーンが提案したように、変更されたステートメントで実行しましたが、機能します。Jonathan が指摘したように、テストすべき時間範囲を明らかに見逃していました。

ジョナサンの説明で、自分の間違いをよりよく理解できるようになり、役に立ちました。

于 2008-12-31T18:14:42.617 に答える
-5

ORが必要だと思います。


SELECT * FROM appts 
WHERE (timeStart >='$timeStart' 
OR timeEnd <='$timeEnd')
AND dayappt='$boatdate'

各レコードが特定の日だけを気にしていると仮定します。つまり、レンタルしたボートは1日を超えて走ることはありません。

于 2008-12-30T05:19:20.170 に答える