1

SPの内部クエリとして使用されるため、最適化したいSQLクエリがあります。

 SELECT TOP 1 @CurrentStartDate = Strt_Dt FROM   (
 SELECT 1 AS seq, Stat, Strt_Dt, Est_Hrs_Comp, EndDate, Tckt_Id, Envr
  FROM   pipeline_rest_envr_info e
  WHERE  e.tckt_id = @TicketID AND stat = 'INPR'
  UNION
  SELECT TOP 1 2 AS seq, Stat, Strt_Dt, Est_Hrs_Comp, EndDate, Tckt_Id, Envr
  FROM   pipeline_rest_envr_info e
  WHERE  e.tckt_id = @TicketID AND stat = 'CMPL'
  ORDER BY enddate DESC
  UNION
  SELECT TOP 1 3 AS seq, Stat, Strt_Dt, Est_Hrs_Comp, EndDate, Tckt_Id, Envr
  FROM   pipeline_rest_envr_info e
  WHERE  e.tckt_id = @TicketID AND stat = 'PLND'
  ORDER BY strt_dt
  UNION 
  SELECT 4 AS seq, 'UNP', NULL, NULL, NULL, tckt_id, 'Unplanned'
  FROM   pipeline_rest_envr_info e
  WHERE  e.tckt_id = @TicketID
) aa
ORDER BY aa.seq

このクエリを使用するより良い方法はありますか。同じタイプのロジックがたくさんあるので、これが必要です。

4

4 に答える 4

2

同じ基準で同じテーブルの4つの結果を結合していますが、CASEステートメントを使用するだけでは不十分ですか?例えば

SELECT 
    CASE Stat
         WHEN 'INPR' THEN 1
         WHEN 'CMPL' THEN 2
         WHEN 'PLND' THEN 3
         WHEN 'Unplanned' THEN 4
         ELSE 0 -- Not sure what your 'ELSE' case would be
    END as Seq,
    etc....
FROM   pipeline_rest_envr_info e 
WHERE  e.tckt_id = @TicketID 

ロジックを持つすべてのフィールドのcaseステートメントは引き続き必要ですが、すべてのデータが含まれ、読みやすくなります。パフォーマンスも大幅に向上するはずです。

于 2012-10-19T11:27:12.123 に答える
2
SELECT TOP 1 @CurrentStartDate = Strt_Dt FROM (
 SELECT 
        CASE stat WHEN 'INPR' THEN 1
                    WHEN 'CMPL' THEN 2
                    WHEN 'PLND' THEN 3
                    ELSE 4 END AS seq ,
        Stat, Strt_Dt, Est_Hrs_Comp, EndDate, Tckt_Id, Envr
  FROM   pipeline_rest_envr_info e
  WHERE  e.tckt_id = @TicketID ) aa
ORDER BY aa.seq

実際、@Charlehと同じ答えです

TOP 1すべてのユニオンから最初のものだけを取るので、2番目と3番目は必要ありません

于 2012-10-19T11:29:57.840 に答える
2

コメントへの返信がない場合、いくつかの仮定を立てます...

シングルには次のtckt_idものがあります。

  • 複数CMPLのアイテム。 (完成?)
  • たったINPR一品。 (進行中?)
  • 複数PLNDのアイテム。 (予定?)
  • その他複数のアイテム。 (無計画?)


あなたが欲しいのstrt_dtは...

  • INPRアイテム (存在する場合) 。
  • それ以外の場合は、最後のCMPLアイテム (存在する場合)。
  • それ以外の場合は、最初のPLNDアイテム (存在する場合)。
  • さもないと、NULL


SELECT
  TOP 1
  @current_start_date
  =
  CASE WHEN stat = 'INPR' THEN MIN(strt_dt)
       WHEN stat = 'CMPL' THEN MAX(strt_dt)
       WHEN stat = 'PLND' THEN MIN(strt_dt)
                          ELSE NULL
  END
FROM
  pipeline_rest_envr_info
WHERE
  tckt_id = @TicketID
GROUP BY
  stat
ORDER BY
  CASE WHEN stat = 'INPR' THEN 1
       WHEN stat = 'CMPL' THEN 2
       WHEN stat = 'PLND' THEN 3
                          ELSE 4 END


これには、1 つの追加の仮定があります。

  • 最後CMPLに終了したアイテムは、最後に開始されたものでもあります

その仮定が間違っていてROW_NUMBER()、 にアクセスできる場合は、代わりにこれを試すことができます...

WITH
  plus_sort_order
(
  SELECT
    ROW_NUMBER() OVER (PARTITION BY stat ORDER BY strt_dt ASC ) AS order_strt,
    ROW_NUMBER() OVER (PARTITION BY stat ORDER BY end_dt  DESC) AS order_end,
    *
  FROM
    pipeline_rest_envr_info
  WHERE
    tckt_id = @TicketID
)
SELECT
  TOP 1
  @current_start_date = strt_dt
FROM
  plus_sort_order
WHERE
  (order_strt = 1) OR (stat = 'CMPL' AND order_end  = 1)
ORDER BY
  CASE WHEN stat = 'INPR' THEN 1
       WHEN stat = 'CMPL' THEN 2
       WHEN stat = 'PLND' THEN 3
                          ELSE 4 END

他にもかなりの数の方法があります。しかし、多くはデータに依存します。ここと他の回答のアイデアを試して、説明/クエリ計画を使用して、利用可能なオプションごとに必要なインデックスを決定することをお勧めします。

于 2012-10-19T12:10:43.260 に答える
0

Temp Table必要に応じてインデックスを作成し、各からレコードを挿入する必要があると思いますUNION。sを使用するよりもいくらか高速UNIONです。

于 2012-10-19T11:36:33.400 に答える