2


0

イベントとアクティビティの2つのエンティティがあるとしましょう。

イベントは、日の出、日没、嵐、霧などのように、(一見)ランダムな時間に起こるものです。

このためのテーブルがあります。

テーブルEventの作成(eventKey int、eventDesc varchar(100)、開始日時)

EventKey | EventDesc | 1 "Sunset"を開始しました2009-07-03 6:51 pm 2 "Sunrise" 2009-07-04 5:33 am 3 "Fog" 2009-07-04 5:52 pm 4 "Sunset" 2009-07-04 6:49 pm 5 "Full Moon" 2009-07-04 10:12 pm 6 "Sunrise" 2009-07-05 5:34 am

それから私は人々が参加した活動と彼らが関係するイベントの表を持っています。 アクションは長期的で複数のイベントにまたがる可能性があります。「週末のキャンプアウト」)

テーブルを作成します。EventTask(activityKey int、activityDesc varchar(100)、startEventKey int、endEventKey int)

ActivityKey | ActivityDesc | StartEventKey | EndEventKey 123 "キャンプアウト" 1 5 234 "ドライブホーム" 6 6

発生したイベントによってマークされたアクションのタイムラインを出力したいです。

ActivityKey | ActivityDesc | EventKey | EventDesc 123 "キャンプアウト" 1 "サンセット" 123 "キャンプアウト" 2 "サンライズ" 123 "キャンプアウト" 3 "フォグ" 123 "キャンプアウト" 4 "サンセット" 123 "キャンプアウト" 5月 "234"ドライブホーム "6"日の出 "
https://stackoverflow.com/questions/1060524[この質問に似ています]線形時間でこれを実行するクエリを書くことは可能ですか? あなたが考えることができるインデックスや他の最適化も推奨してください。 現在の解決策はC#で書かれていますが、私は速いSQLの解決策を望みます。

これを行うための最適なクエリは何ですか?

3 Answer


2


/ *テーブルEventを作成する(eventKey int、eventDesc varchar(100)、開始タイムスタンプ);

イベント値に挿入(1、 'Sunset'、 '2009-07-03 6:51 pm');イベント値に挿入(2、 'Sunrise'、 '2009-07-04 5:33 am');イベント値に挿入(3、 'Fog'、 '2009-07-04 5:52 pm');イベント値に挿入(4、 'Sunset'、 '2009-07-04 6:49 pm');イベント値に挿入します(5、「満月」、「2009-07-04 10:12 pm」)。イベント値に挿入(6、 'Sunrise'、 '2009-07-05 5:34 am');

イベントから*を選択します。

テーブルを作成します。EventTask(activityKey int、activityDesc varchar(100)、startEventKey int、endEventKey int)

イベントタスク値に挿入(123、 'Camp-out'、1、5);イベントタスクの値に挿入(234、 'ドライブホーム'、6、6);

eventtaskから*を選択します。

* /

a.starteventkeyとa.endeventkeyの順序で、a.activitykey、b.eventkeyの順に選択します。

activitykey activitydescイベントキーeventdesc -------------- --------------- ----------- ------ ------ 123キャンプアウト1日没123キャンプアウト2日の出123キャンプアウト3霧123キャンプアウト4日没123キャンプアウト5満月234ドライブホーム6日の出

6レコードが選択されています[メタデータの取得:3 / ms] [データの取得:1 / ms]

[執行:7/7/09 4:24:34 PM EDT] [執行:15 / ms]

テーブルが大きい場合は、必ずevent.eventkey、eventtask.starteventkey、およびeventtask.endeventkeyのインデックスが必要です。

インデックスはクエリ速度を向上させますが、挿入と更新は遅くなります。

これは、event.eventkey列に意味を持たせる必要のないバージョンです(より正確です)。

eventtaskからa.activitykey、a.activitydesc、d.eventkey、d.eventdescを選択します。b。でイベントを結合します。b。eventkey = a.starteventkey cでイベントを結合します。 a.activitykeyによる開始および開始の順序、d.started。

activitykey activitydescイベントキーeventdesc -------------- --------------- ----------- ------ ------ 123キャンプアウト1日没123キャンプアウト2日の出123キャンプアウト3霧123キャンプアウト4日没123キャンプアウト5満月234ドライブホーム6日の出

6レコードが選択されています[メタデータ取得:2 / ms] [データ取得:0 / ms]

[実行:7/8/09 10:01:25 AM EDT] [実行:4 / ms]


1


ランダムイベントを基にするのではなく、アクティビティテーブルを再定義して、startTimeとEndTimeを設定します。 それでは、その間にどのような「イベント」が発生していたのかを知りたいのであれば、その時間帯に参加します。 これはオブジェクト指向/柔軟性の観点からはより理にかなっていますが、パフォーマンスのコストが大きくなります。

@Eventテーブルを宣言します(id int、name varchar(100)、
[time]
日付時刻 );

@Event値に挿入(1、 'Sunset'、 '2009-07-03 6:51 pm'); @Event値に挿入します(2、 'Sunrise'、 '2009-07-04 5:33 am'); @Event値に挿入(3、 'Fog'、 '2009-07-04 5:52 pm'); @Event値に挿入します(4、 'Sunset'、 '2009-07-04 6:49 pm')。 @Event値に挿入します(5、 'Full Moon'、 '2009-07-04 10:12 pm')。 @Event値に挿入(6、 'Sunrise'、 '2009-07-05 5:34 am');

@Eventから*を選択します。

@Activityテーブルを宣言する(id int、name varchar(100)、startTime datetime、endTime datetime)

@Activity値(123、 'Camp-out'、 '2009-07-03 6:00 pm'、 '2009-07-05 5:00 am')に挿入します。 @Activityの値に挿入します(234、 'ドライブホーム'、 '2009-07-05 5:00 am'、 '2009-07-05 6:00 am')。

@Activity AからEを選択します。E. [time]> A.startTimeおよびE. [time] <A.startTimeによるA.endTimeの順序で@Event Eを結合します。


1


私は最近そのようなクエリを最適化するための2つの方法を書いた(BETWEEN条件での参加): -between-conditions.aspx [COSS APPLYを使用してBETWEEN条件で結合を最適化する]

可能な問い合わせ(サンプルINSERTなしでテストすることは不可能):

SELECT et.activityKey、et.activityDesc、e。* Event AS eからの適用の適用(SELECT TOP 1 * from EventTask AS etの場所et.startEventKey <= e.startedおよびe.started <endEventKeyの順序)