0

次の列を持つテーブルがあります

  • 一意でない ID
  • さまざまなデータの n 列

データが更新された日付

日付範囲を指定すると、その日付範囲内に更新されたエントリのリストと、見つかった直前の更新のエントリを取得するクエリがあります。通常、日付範囲は 1 日以内なので、2013 年 7 月 10 日 00:00:000 ~ 2013 年 7 月 11 日 00:00:000 です。

例えば。2013 年 7 月 10 日 00:00:000 ~ 2013 年 7 月 11 日 00:00:000 を指定すると、クエリは 2 つのエントリを検出しました

id   new data      updatedate              old data     last updatedate
3    randomdata    7-10-2013 03:30:343     randomdata   7-05-2013 06:34:764
4    randomdata    7-10-2013 13:30:343     randomdata   6-09-2013 04:37:376

これは私が得たい結果です。現在、これを行うクエリが既にありますが、多くのエントリを持つテーブルに 3 つの内部結合があるため、クエリが遅くなり、クエリを高速化する方法を誰かが考えられるかどうか疑問に思っていました。SQL Server 2000 を使用しています。

テーブル情報

  • 一意でない ID
  • 一意の ID (これは単なる自動インクリメント ID です)
  • 収集するさまざまなデータ
  • 更新日

編集:

インデックスは現在オンでidあり、updatedate

現在使用しているクエリ (一般化) ::WARNING::きれいではありません::WARNING::

select * 
from 
    (select distinct 
        s1.id as id, 
        s1.randData1, s2.randData1, s1.randData2, s2.randData2,..., 
        s1.updatedate as newupdatedate,
        s2.updatedate as prevupdatedate, 
        datediff(second, s1.updatedate ,s2.updatedate) as maxdate 
     from 
        (select * 
         from updates 
         where updatedate >= '{0}' and updatedate < '{1}' 
           and id in ('{3}')) as s1 
     inner join 
        updates s2 on s1.id = s2.id and s1.updateid != s2.updateid) as t1 
 inner join 
     (select 
          s1.id, max(datediff(second, s1.updatedate, s2.updatedate)) as maxdate2 
      from updates s1 
      inner join updates s2 on s1.id in ('{3}') and s1.id = s2.id and s1.updateid != s2.updateid 
      where datediff(second, s1.updatedate, s2.updatedate) < 0
        and s1.updatedate < '{1}' and s2.updatedate < '{1}' 
      group by 
         s1.id) as t2 on t1.id = t2.id and t1.maxdate = t2.maxdate2

{0} {1} と {2} は、渡されるパラメーターです。

編集:違いがある場合、クエリはC#で実行されています。必要に応じて、2 つのクエリも有効です。私が最終的に探しているのは、選択した日付のデータで何が変更されたかです。

4

2 に答える 2

0

一時テーブルを使用してみてください -

IF OBJECT_ID (N'tempdb.dbo.#temp') IS NOT NULL
   DROP TABLE #temp

SELECT *
INTO #temp
FROM dbo.updates
WHERE ID IN ('{3}')

SELECT * 
FROM 
    (
     SELECT DISTINCT 
             s1.id AS id, 
             s1.randData1, s2.randData1, s1.randData2, s2.randData2,
             s1.updatedate AS newupdatedate,
             s2.updatedate AS prevupdatedate, 
             DATEDIFF(second, s1.updatedate ,s2.updatedate) AS maxdate 
     FROM 
     (
          SELECT *
          FROM #temp
          WHERE updatedate BETWEEN '{0}' AND '{1}'
     ) s1 
     JOIN #temp s2 ON s1.id = s2.id AND s1.updateid != s2.updateid
) t1 
JOIN (
     SELECT 
          s1.id, 
          MAX(DATEDIFF(second, s1.updatedate, s2.updatedate)) AS maxdate2 
     FROM #temp s1 
     JOIN #temp s2 ON s1.id = s2.id AND s1.updateid != s2.updateid 
     WHERE DATEDIFF(second, s1.updatedate, s2.updatedate) < 0
          AND s1.updatedate < '{1}' AND s2.updatedate < '{1}' 
     GROUP BY s1.id
) t2 ON t1.id = t2.id AND t1.maxdate = t2.maxdate2
于 2013-07-18T06:06:48.737 に答える
0

ネストされたすべての select ステートメントを #Temp Tables に入れることができたのはかなり幸運でした。実際に話している大きさに応じて、テーブル変数を使用できる可能性があります。

また、クエリを段階的に再確認して、ネストされた各クエリでそのすべてのデータを長く運ぶ必要があるかどうかを確認することもできます。言い換えれば、ネストされたすべてのクエリが外側のクエリによって消費されるか、余分なデータがやってくるかということです。

ここで見られる複雑さでは、一時テーブルを使用するのが最善の策だと思います。そうすれば、ネストされたすべてのクエリで、一時テーブルをメモリに保持する代わりに構築できます。

最終的なクエリは、はるかにコンパクトで高速になります。

于 2013-07-18T03:46:49.470 に答える