2

MySQLテーブルから行を取得するための最良の方法(パフォーマンス)を知りたいのですが、2つの日付型フィールドが一緒になって特定の時間枠を構成し、問題の時間枠のどこかに特定の曜日があります。

与えられたテーブル構造とデータの例を想定すると、たとえば、月曜日が数値2で参照されている場合など、保存された時間枠に月曜日が1回以上出現するすべての行を取得する最良の方法は何でしょうか。

Table: ExampleA
Fields:
ID (int) | Begin (date) | End (date)
------------------------------------
1        |  2012-02-14  | 2012-02-16
2        |  2012-01-01  | 2012-01-15
3        |  2012-03-04  | 2012-03-06
4        |  2012-01-23  | 2012-02-07
5        |  2012-07-15  | 2012-07-15
6        |  2012-03-06  | 2012-03-13

クエリの例では、日曜日から土曜日に終わり、それぞれ1から7のインデックス位置を構成する、ゼロ以外のベースのインデックスで特定の曜日を参照することが推奨されます。(MySQL関数DAYOFWEEKと同じです。)

アップデート:

与えられた時間枠で毎日繰り返す方法を何らかの方法で検討していて、見栄えがよくありません。一時テーブルなどを作成する要件は実用的ではなく、同時ユーザーが同じ要件のアクションを要求すると、問題が発生します。

例:mysqlを使用して2つの指定された日付の間の日付のリストを取得するにはどうすればよいですか?

最初のアイデアは、各行の時間枠の各日をループすることでした。次に、各時間枠について、開始日から終了日まで日ごとに調べ、各時間枠(行)で検出された曜日のリストを返します。確かに速い方法ではありませんが、始めるための何かです。これよりも優れた推奨事項やその他の提案はありますか?

更新2:

G-Nuggetは、各曜日に1つずつ7つのブールフィールドを作成することを 提案しました。新しい行を追加するときは、その行の時間枠で見つかった曜日に該当するフィールドをtrueとマークします。もちろん、これはSQLクエリ自体ではなく、データベースを使用するアプリケーションによって実行されます。

これは、これまでに見た、または見た中で最も単純でパフォーマンスへの影響が最も少ないソリューションですが、テーブルスキーマを編集することはできません。

更新3:

この質問をさらに明確にするために、誰かが混乱したり誤読したりした場合に備えて。ノート:

月曜日の曜日、または時間枠内のどこか(「Being」から「End」まで)の「Begin」、「End」のいずれかで選択した別の週の日を見つけることができる行を取得しようとしています。 、または「開始」から「終了」までの期間に沿って

更新4:

ここに、この質問のSQLフィドルがあり、マシンにテーブルを作成しなくても、アイデアを試すことができます。

更新5-解決策:

Alexey Gerasimovの 回答を使用して、彼のwhere句ロジックを自分の問題に適用し、解決策を実行することができました。アレクセイに感謝します。

これを読んで試してみて、ニーズに合っているかどうかを確認したい場合:

このSQLFiddleまたはこの小さなクエリを使用して、彼のソリューションをセットアップして実行できます。

# Create table
CREATE TABLE `ExampleA` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Begin` date NOT NULL,
  `End` date NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

# Insert demo data
INSERT INTO `ExampleA`(`ID`,`Begin`,`End`) VALUES  
(1,'2012-02-14','2012-02-16'),
(2,'2012-01-01','2012-01-15'),
(3,'2012-03-04','2012-03-06'),
(4,'2012-01-23','2012-02-07'),
(5,'2012-07-15','2012-07-15'),
(6,'2012-03-06','2012-03-13');

# Query to retrieve rows which time frame
# has one or more occurrences of a given weekday
#
# 1 Sunday
# 2 Monday
# 3 Tuesday
# 4 Wednesday
# 5 Thursday 
# 6 Friday
# 7 Saturday

SET @MYDAYOFWEEK=2;
SELECT * FROM ExampleA
WHERE
(
        ( @MYDAYOFWEEK >= DAYOFWEEK(BEGIN) AND @MYDAYOFWEEK <= DAYOFWEEK(BEGIN) + DATEDIFF(END,BEGIN) )
    OR  
        ( 
          @MYDAYOFWEEK+7 >= DAYOFWEEK(BEGIN) AND @MYDAYOFWEEK+7 <= DAYOFWEEK(BEGIN) + DATEDIFF(END,BEGIN) 
        )
)
4

2 に答える 2

1

データが現在どのように設定されているかで、あなたが求めていることを行うための「良い」方法はありません。2つの日付を読み取るまで範囲内の日がわからないため、このクエリでインデックスを使用することはできません。

クエリのパフォーマンスを向上させるための1つの可能な方法は、毎日のインジケータフィールド(TINYINTまたはのようなものCHAR(1))を持つことです。これ役立つ可能性がありますが、一般に、サイズとインデックスが増えるため、実際にはテーブルの速度が低下する可能性があります。1日または2日で何かが起こったかどうかを知る必要があるだけの場合、このオプションは機能しますが、2日または3日以上必要な場合は、追加のサイズがメリットを上回る可能性があります。

于 2013-01-11T17:32:20.877 に答える
1

このようなものはどうですか:

select * from ExampleA
where ID = MYDAYOFWEEK
and (
        ( id >= dayofweek(begin) and id <= dayofweek(begin) + DATEDIFF(end,begin) )
    OR  
        ( 
        id+7 >= dayofweek(begin) and id+7 <= dayofweek(begin) + DATEDIFF(end,begin) 
        )
    )   

最初のチェックは同じ週の日と一致し、2番目のチェックはスパンする週を処理します。ただし、これが最高のパフォーマンスのクエリであるかどうかはわかりません

アップデート

ごめん。最初の列は曜日だと思いました。修正するには、クエリを次のように変更するだけです。

select * from ExampleA
where (
        ( MYDAYOFWEEK >= dayofweek(begin) and MYDAYOFWEEK <= dayofweek(begin) + DATEDIFF(end,begin) )
    OR  
        ( 
        MYDAYOFWEEK+7 >= dayofweek(begin) and MYDAYOFWEEK+7 <= dayofweek(begin) + DATEDIFF(end,begin) 
        )
    )  

これは間違いなくスピーディーではありません

于 2013-01-11T18:12:06.923 に答える