使用一堆联盟和条件优化SQl查询

时间:2015-12-31 01:30:40

标签: sql sql-server performance query-optimization

我根据传递的参数编写了一个查询,以获得第一班,第二班,第三班或所有班次的生产数量。

班次时间如下:

1st: 06:00 - 14:00
2nd: 14:00 - 22:00
3rd: 22:00 - 06:00

我的查询如下:

// Param.1 = date start , Param.2 = date end , Param.3 = shift start time , Param.4 = shift end time
// Param.5 = 1 when ShiftStarttime < ShiftEndtime ( Param.1 = 2015-12-26T06:00:00,  param.2 = 2015-12-26T14:00:00, param.3 = 6 , param.4 = 10 )
// Param.5 = 2 when ShiftStarttime > ShiftEndtime ( Param.1 = 2015-12-26T22:00:00,  param.2 = 2015-12-27T06:00:00, param.3 = 22 , param.4 = 2 )
// Param.5 = 3 when all of the shifts ( Param.1 = 2015-12-26T06:00:00,  param.2 = 2015-12-27T06:00:00)

SELECT 

      B.Machine_NAME,
      C.Part_Name,     
      SUM(A.QT_CONFIRMED) QT_CONFIRMED,
      D.SCRAP_REASON

 FROM 
       CONFIRMATION A 

       INNER JOIN MACHINE B ON A.Machine_ID =B.Machine_ID  
       INNER JOIN PART C ON B.Part_ID = C.Part_ID
       LEFT JOIN SCRAP_REASON D ON A.SCRAP_REASON_ID =D.SCRAP_REASON_ID

WHERE

      '[Param.5]' = '1'
       AND (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]') AND ((DATEPART(hour, DT_CONFIRMATION) >= '[Param.3]') AND (DATEPART(hour, DT_CONFIRMATION) < '[Param.4]'))

GROUP BY

      B.Machine_NAME,
      C.Part_Name,
      D.SCRAP_REASON

UNION


SELECT 

      B.Machine_NAME,
      C.Part_Name,     
      SUM(A.QT_CONFIRMED) QT_CONFIRMED,
      D.SCRAP_REASON

 FROM 
       CONFIRMATION A 

       INNER JOIN MACHINE B ON A.Machine_ID =B.Machine_ID  
       INNER JOIN PART C ON B.Part_ID = C.Part_ID
       LEFT JOIN SCRAP_REASON D ON A.SCRAP_REASON_ID =D.SCRAP_REASON_ID


WHERE

      '[Param.5]' = '2'
       AND (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]') AND (DATEPART(hour, DT_CONFIRMATION) BETWEEN 22 AND 23 OR  DATEPART(hour, DT_CONFIRMATION) BETWEEN 0 and 5)

GROUP BY

      B.Machine_NAME,
      C.Part_Name,
      D.SCRAP_REASON

UNION


SELECT 

      B.Machine_NAME,
      C.Part_Name,     
      SUM(A.QT_CONFIRMED) QT_CONFIRMED,
      D.SCRAP_REASON

 FROM 
       CONFIRMATION A 

       INNER JOIN MACHINE B ON A.Machine_ID =B.Machine_ID  
       INNER JOIN PART C ON B.Part_ID = C.Part_ID
       LEFT JOIN SCRAP_REASON D ON A.SCRAP_REASON_ID =D.SCRAP_REASON_ID


WHERE

      '[Param.5]' = '3'
    AND (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]') 

GROUP BY

      B.Machine_NAME,
      C.Part_Name,
      D.SCRAP_REASON

因此基本上取决于移位开始时间和移位结束时间,仅在eof上,由于Param.5参数,将执行查询的并集。请查看查询中的COMMENT以了解参数。

此查询运行正常并提供正确的结果,但我确信它可以优化以便运行得更快,如果我可以删除Union或可以修改它的某些部分。

有没有人有更好的想法以更优化的方式编写此查询?如果是,请分享。

2 个答案:

答案 0 :(得分:1)

WHERE子句外,两个查询看起来完全相同。尝试使用WHERE将两个OR子句连接到一个查询中。请注意,我在DISTINCT语句中添加了SELECT,以确保仍然删除重复项(UNION运算符在原始查询中执行的操作)。

SELECT DISTINCT
    B.Machine_NAME,
    C.Part_Name,     
    SUM(A.QT_CONFIRMED) QT_CONFIRMED,
    D.SCRAP_REASON
FROM 
    CONFIRMATION A
INNER JOIN MACHINE B ON A.Machine_ID = B.Machine_ID  
INNER JOIN PART C ON B.Part_ID = C.Part_ID
LEFT JOIN SCRAP_REASON D ON A.SCRAP_REASON_ID = D.SCRAP_REASON_ID
WHERE
    (
        '[Param.5]' = '1' AND
        (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]') AND
        (
            (DATEPART(hour, DT_CONFIRMATION) >= '[Param.3]') AND
            (DATEPART(hour, DT_CONFIRMATION) < '[Param.4]')
        )
    )
    OR
    (
         '[Param.5]' = '2' AND
         (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]') AND
         (
             DATEPART(hour, DT_CONFIRMATION) BETWEEN 22 AND 23 OR
             DATEPART(hour, DT_CONFIRMATION) BETWEEN 0 and 5
         )
    )
GROUP BY
    B.Machine_NAME,
    C.Part_Name,
    D.SCRAP_REASON

答案 1 :(得分:0)

除了WHERE子句之外,查询都具有相同的结构。因此,您可以使用OR

组合条件
 SELECT B.Machine_NAME,  C.Part_Name, SUM(A.QT_CONFIRMED) as QT_CONFIRMED,
        D.SCRAP_REASON
 FROM CONFIRMATION A INNER JOIN
      MACHINE B
      ON A.Machine_ID = B.Machine_ID INNER JOIN
      PART C
      ON B.Part_ID = C.Part_ID LEFT JOIN
      SCRAP_REASON D
      ON A.SCRAP_REASON_ID = D.SCRAP_REASON_ID
WHERE ('[Param.5]' = '1' AND
       (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]') AND 
       ((DATEPART(hour, DT_CONFIRMATION) >= '[Param.3]') AND 
        (DATEPART(hour, DT_CONFIRMATION) < '[Param.4]'))
      ) OR
      ('[Param.5]' = '2' AND
       (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]') AND 
       (DATEPART(hour, DT_CONFIRMATION) BETWEEN 22 AND 23 OR
        DATEPART(hour, DT_CONFIRMATION) BETWEEN 0 and 5)
      ) OR
      ('[Param.5]' = '3' AND (A.DT_CONFIRMATION BETWEEN '[Param.1]' AND '[Param.2]')
      );