1

我有一个 SQL 查询,我想优化它作为 SP 的内部查询。

 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因为你只取所有工会的第一个

于 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


这确实有一个额外的假设:

  • 最后完成的任何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索引,然后从每个UNIONs 中插入记录。这比使用UNIONs 快一些。

于 2012-10-19T11:36:33.400 回答