1

タスクのリストを保持するためのテーブルがあり、これらのタスクは特定の日時に処理する必要があります。トリッキーな部分は、これらのタスクが再帰的に実行されることです。実行時間は、5つの異なるパラメーターに基づいて計算する必要があります。

UDFを介した実行時間の計算は、単純な部分でした。

Function dbo.task_next_run(
    @task_type varchar(10),
    @task_schedule_day_of_week varchar(20),
    @task_schedule_time varchar(20),
    @task_period smallint,
    @last_run datetime
)
Returns datetime
...
...
...
Return @next_run

私の最後のタスククエリはこれでした:

SELECT id, 
       task_name, 
       last_run 
From tasks 
Where dbo.task_next_run
(
   task_type, @task_schedule_day_of_week, 
   @task_schedule_time, @task_period, @last_run
) < getdate() and 
dbo.task_next_run
(
     task_type, @task_schedule_day_of_week, 
     @task_schedule_time, @task_period, @last_run
) > last_run

私の問題は、where句で同じ関数を2回実行することです。where句のエイリアスとして計算値を使用するソリューションが必要です。

4

3 に答える 3

4

なぜあなたはしないのですか:

DECLARE @now DATETIME = CURRENT_TIMESTAMP;

SELECT id, task_name, last_run
FROM 
(
  SELECT id, task_name, last_run, d = dbo.task_next_run
  (task_type, @task_schedule_day_of_week, @task_schedule_time, @task_period, @last_run)
  From tasks 
) AS x
WHERE x.d < @now
AND x.d > x.last_run;

私は、SQL Serverがそれを同じものにまとめ、関数を2回ではなく1回だけ呼び出すことを確信しています。ただし、関数の性質によっては、行ごとに 1 回実行される場合があります。UDF をインライン テーブル値関数に変換することを検討しましたか? これらは一般に、はるかに最適化されます。

別のオプションは次のとおりです(コメントで説明されているように):

DECLARE @now DATETIME = CURRENT_TIMESTAMP;

DECLARE @d TABLE(task_type INT PRIMARY KEY, post DATETIME);

INSERT @d SELECT task_type, dbo.task_next_run(task_type, @variables)
  FROM (SELECT task_type FROM dbo.tasks GROUP BY task_type);

今、あなたは言うことができます:

SELECT t.id, t.task_name, t.last_run
FROM dbo.tasks AS t
INNER JOIN @d AS d
ON t.task_type = d.task_type
AND t.last_run > d.post
WHERE d.post < @now;

最初にさらにフィルタリングすることもできます。

DELETE @d WHERE post >= @now;

これにより、上記の WHERE を削除できます。

結局のところ、同じように最適化する可能性はありますが、わずかに優れたパフォーマンスを試してみる価値があるかもしれません (変数が多すぎて、30,000 フィートから予測することはできません)。

于 2012-08-30T17:23:03.827 に答える
2

Cross Applyは私が必要としていたものです。Cross Apply を使用した最終的なクエリを次に示します。

SELECT id, task_name, last_run, func.next_run
FROM tasks
Cross Apply (Select dbo.task_next_run(task_type, @task_schedule_day_of_week, @task_schedule_time, @task_period, @last_run) as next_run) as func
WHERE 
func.next_run < getdate() and
func.next_run > last_run
于 2012-08-30T17:21:38.850 に答える
-1
SELECT id, 
       task_name, 
       last_run 
       From tasks 
WHERE dbo.task_next_run
      (
            task_type, @task_schedule_day_of_week, 
            @task_schedule_time, @task_period, @last_run
      ) BETWEEN  last_run AND getdate() 
于 2012-08-30T17:25:18.693 に答える