4

曜日と時間を唯一の情報として使用して、一連の日付を取得する必要があります。

この操作の逆、つまり WEEKDAY(date) または DAYOFWEEK(date) を使用していることは認識していますが、これは必要なものではありません。

このようなテーブルがあり、継続的にスキャンされ、現在の日付と比較されます。

+----+---------+----------+----------+
| id | weekday | start    | end      |
+----+---------+----------+----------+
|  1 |       1 | 09:00:00 | 17:00:00 |
|  2 |       2 | 09:00:00 | 17:00:00 |
|  3 |       3 | 09:00:00 | 17:00:00 |
|  4 |       4 | 23:00:00 | 17:00:00 |
|  5 |       5 | 18:00:00 | 23:00:00 |
|  6 |       6 | 00:00:00 | 00:00:00 |
|  7 |       7 | 00:00:00 | 01:00:00 |
+----+---------+----------+----------+

上記は単純なバージョンです。このテーブルには数百または数千の反復があると予想されます。4 行目に見られるように、時間も深夜を超える可能性があり、それを補う必要があります。

次の結果セットを提供するクエリが必要ですが、現在の年、月、および平日の列から渡された曜日に基づいて、日付をロックするのに問題があります。

結果セットの例:

+---------------------+---------------------+
| start               | end                 |
+---------------------+---------------------+
| 2013-06-24 09:00:00 | 2013-06-24 17:00:00 |
| 2013-06-25 09:00:00 | 2013-06-25 17:00:00 |
| 2013-06-26 09:00:00 | 2013-06-26 17:00:00 |
| 2013-06-27 23:00:00 | 2013-06-28 17:00:00 | # <---- Notice the date difference here
| 2013-06-28 18:00:00 | 2013-06-28 23:00:00 |
| 2013-06-29 00:00:00 | 2013-06-30 00:00:00 | # <---- Also here, the span is 24 hours
| 2013-06-30 00:00:00 | 2013-06-30 01:00:00 |
+---------------------+---------------------+

現在の日付のみを取得することに近づいていますが、これらの日付を後で変換する必要があるため、現在の日付だけでなく、それらすべての配列が必要です。日々。

編集:現在のコードを投稿しました:これが正しい方向に向かっているとは思いませんが

SELECT  TIMESTAMP(IF (end < start,
                     CURRENT_DATE,
                     SUBDATE(CURRENT_DATE, 1)),
                  start) AS 'start',

        TIMESTAMP(IF (end < start,
                     CURRENT_DATE,
                     SUBDATE(CURRENT_DATE, 1))
                  end) AS 'end',

  FROM  shift

そして結果:

+---------------------+---------------------+
| start               | end                 |
+---------------------+---------------------+
| 2013-06-27 23:00:00 | 2013-06-28 17:00:00 | 
| 2013-06-28 18:00:00 | 2013-06-28 23:00:00 | # Needs the rest of the dates of the week
+---------------------+---------------------+

2回目の編集

以下のコメンターの助けのおかげで、私は以下のクエリにたどり着きましたが、先に進みますが、デザインに懸念を表明する人もいるので、答えを決める前にいくつかのテストを実行します. これを実現するためのより良い方法があれば、私はそれを聞くことに本当に興味があります!

最良のポイントは、クエリの途中で月が変わるときだと思います。曜日を使用して違いを判断するのは面倒かもしれません。

クエリ:

SELECT  @diff:=(CAST(weekday AS SIGNED) - (WEEKDAY(CURRENT_DATE) + 1)) as 'diff',
        @date:=DATE_ADD(CURRENT_DATE, INTERVAL @diff DAY) as 'start_date',
        TIMESTAMP(@date, start) AS 'start',
        TIMESTAMP(IF (end <= start,
                     DATE_ADD(@date, INTERVAL 1 DAY),
                     @date),
                  end) AS 'end'
 FROM   shift

結果:

+------+------------+---------------------+---------------------+
| diff | start_date | start               | end                 |
+------+------------+---------------------+---------------------+
|   -4 | 2013-06-24 | 2013-06-24 09:00:00 | 2013-06-24 17:00:00 |
|   -3 | 2013-06-25 | 2013-06-25 09:00:00 | 2013-06-25 17:00:00 |
|   -2 | 2013-06-26 | 2013-06-26 09:00:00 | 2013-06-26 17:00:00 |
|   -1 | 2013-06-27 | 2013-06-27 23:00:00 | 2013-06-28 17:00:00 |
|    0 | 2013-06-28 | 2013-06-28 18:00:00 | 2013-06-28 23:00:00 |
|    1 | 2013-06-29 | 2013-06-29 00:00:00 | 2013-06-30 00:00:00 |
|    2 | 2013-06-30 | 2013-06-30 00:00:00 | 2013-06-30 10:00:00 |
+------+------------+---------------------+---------------------+

3 回目の編集

月の初めと終わりにまたがる期間にわたって上記のクエリをテストし、その目的に適していることがわかりました。上記のクエリといくつかのメモを回答に移動して、誰かがこれを役に立つと思うかもしれません将来。

その点について、さまざまなコメンターからのさまざまな落とし穴や推奨事項も含めます。時間を割いて助けてくれたすべての人に感謝します.

4

2 に答える 2

0

それをかなりハッキングした後、将来誰かが同様の問題に遭遇した場合に備えて、以下に提示する答えにたどり着きました. 時間を割いて助けてくれたすべての人に感謝したいと思います。さまざまな回答が非常に役立つことがわかりました。調査結果を以下にリストします。

私が最終的に得たクエリは次のとおりです。

SELECT  @diff:=(CAST(weekday AS SIGNED) - (WEEKDAY(CURRENT_DATE) + 1)) as 'diff',
        @date:=DATE_ADD(CURRENT_DATE, INTERVAL @diff DAY) as 'start_date',
        CONVERT(TIMESTAMP(@date, start) USING latin1) AS 'start',
        CONVERT(TIMESTAMP(IF (end <= start,
                     DATE_ADD(@date, INTERVAL 1 DAY),
                     @date),
                  end) USING latin1) AS 'end'
 FROM   shift

そこではかなりの数のことが起こっています:

  1. まず、現在の平日と表にリストされている曜日との差を取得することを目指しています。
  2. 私のテーブルの平日の列は、実際には UNSIGNED INTEGER によって参照されていたため、その差が負である日の差を取得することができませんでした。
  3. 上記の問題は、CAST 関数を使用することで解決されました。代わりに、負数を許可する SIGNED 整数にキャストする必要がありました。
  4. @date 変数は、クエリの他の場所で使用するためのプレースホルダーとしてのみ使用されています。
  5. TIMESTAMP 関数は、文字列または日付データではなくバイト配列を C# に返していました。この問題を修正した latin1 への変換を指摘してくれた AbsoluteZERO に感謝します。

上記のクエリは、目的の結果である次のデータを返します。テーブルは UTC で設定され、チェックされる時刻はビジネス ロジックで C# によって変換されるため、このような計算で夏時間によって発生する可能性のある問題を回避するには、これで十分です。

結果データ:

+------+------------+---------------------+---------------------+
| diff | start_date | start               | end                 |
+------+------------+---------------------+---------------------+
|   -4 | 2013-06-24 | 2013-06-24 09:00:00 | 2013-06-24 17:00:00 |
|   -3 | 2013-06-25 | 2013-06-25 09:00:00 | 2013-06-25 17:00:00 |
|   -2 | 2013-06-26 | 2013-06-26 09:00:00 | 2013-06-26 17:00:00 |
|   -1 | 2013-06-27 | 2013-06-27 23:00:00 | 2013-06-28 17:00:00 |
|    0 | 2013-06-28 | 2013-06-28 18:00:00 | 2013-06-28 23:00:00 |
|    1 | 2013-06-29 | 2013-06-29 00:00:00 | 2013-06-30 00:00:00 |
|    2 | 2013-06-30 | 2013-06-30 00:00:00 | 2013-06-30 10:00:00 |
+------+------------+---------------------+---------------------+

これが誰かに役立つことを願っています。

于 2013-06-28T05:36:46.863 に答える