SQL-中断查询

时间:2019-05-14 08:12:30

标签: sql sql-server

我从旧版应用程序获得以下查询,而在执行此查询时,它花费了太多时间进行响应。因此,我打算将这个复杂的查询分解为多个查询,并在应用程序端(即较新的应用程序)中执行一些操作。

 WITH members    AS (       
    SELECT
    shift_group_code,
    shift_code,
    0 AS isCycle,
    CHAR(10) + CAST(shift_group_code AS varchar(max)) + CHAR(10) AS [path]       
    FROM shift_grouping       
    WHERE workspace_code IN ('default', 'test', 'test1')       
    AND shift_group_code = 'WS+DEFAULT'       
UNION
ALL       
    SELECT
    H.shift_group_code,
    H.shift_code,
    CASE                  
        WHEN M.[path] LIKE '%' + CHAR(10) + CAST(H.shift_code AS varchar(max)) + CHAR(10) + '%'                  
        THEN 1                  
        ELSE 0              
    END AS isCycle,
    M.[path] + CAST(H.shift_code AS varchar(max)) + CHAR(10) AS [path]       
    FROM
    shift_grouping H       

    JOIN
    members M       
        ON H.shift_group_code = M.shift_code       
        AND M.shift_code       IN (SELECT
            code 
    FROM
        shift_group)       
    WHERE
    H.workspace_code       IN ('default', 'test', 'test1')       
    AND M.isCycle = 0)       

    SELECT
        *       
    FROM shift       
    WHERE
        workspace_code       IN (
            'default', 'test', 'test1'
        )       
        AND (
            code = 'WS+DEFAULT'            
            OR code IN (
                SELECT
                    DISTINCT shift_code                        
                FROM
                    members                         
                WHERE
                    isCycle = 0
            )
        )

我可以在UNION之前破坏第一部分

SELECT shift_group_code, shift_code,
        0 AS isCycle,
        CHAR(10) + CAST(shift_group_code AS varchar(max)) + CHAR(10) AS [path]       
FROM shift_grouping       
WHERE workspace_code       IN ('default', 'test', 'test1')       
AND shift_group_code = 'WS+DEFAULT'

但是查询的第二部分

SELECT H.shift_group_code, H.shift_code,
        CASE                  
            WHEN M.[path] LIKE '%' + CHAR(10) + CAST(H.shift_code AS varchar(max)) + CHAR(10) + '%'                  
            THEN 1                  
            ELSE 0              
        END AS isCycle,
        M.[path] + CAST(H.shift_code AS varchar(max)) + CHAR(10) AS [path]       
 FROM shift_grouping H       
 JOIN members M 
 ON H.shift_group_code = M.shift_code       
 AND M.shift_code IN (SELECT code FROM shift_group)       
 WHERE H.workspace_code IN ('default', 'test', 'test1')

我无法中断,因为有一个JOIN members M语句不允许我中断SQL。

members来自较大查询开始时的WITH members语句。

或者我无法理解他们如何将membersshift_grouping结合在一起。

有人可以为我打断此查询吗?

1 个答案:

答案 0 :(得分:1)

在没有更多有关数据库模式的知识的情况下,很难优化该查询,但是它可以帮助您了解其运行情况。

我还用IN条件替换了EXISTS,它将为您提供更好的性能,但我认为这还不够

成员是公用表表达式(CTE),当调用它本身称为递归CTE时,它定义了一个临时结果集。

SHIFT_GROUPING似乎是您的层次结构表,因此,第一个SELECT语句定义CTE的起始位置,UNION ALL之后的SELECT定义迭代

通常,递归CTE包含三个部分:

  1. 返回CTE基本结果集的初始查询。的 初始查询称为锚成员。
  2. 一个递归查询 引用公共表表达式,因此,它称为 递归成员。递归成员与锚点联合 成员使用UNION ALL运算符。
  3. 终止条件 在终止执行的递归成员中指定 递归成员。

递归CTE的执行顺序如下:

  • 首先,执行锚成员以形成基本结果集(R0),并将此结果用于下一次迭代。
  • 第二,使用上一次迭代的输入结果集(Ri-1)执行递归成员,并返回子结果集(Ri),直到满足终止条件为止。
  • 第三,使用UNION ALL运算符组合所有结果集R0,R1,... Rn,以产生最终结果集。

     ;WITH members    AS --CTE Declaration    
     (   
        -- Defines the initial query of the CTE
         SELECT
         shift_group_code,
         shift_code,
         0 AS isCycle,
         CHAR(10) + CAST(shift_group_code AS varchar(max)) + CHAR(10) AS [path]       
         FROM shift_grouping       
         WHERE workspace_code IN ('default', 'test', 'test1')       
         AND shift_group_code = 'WS+DEFAULT'       
    
        UNION ALL       
    
        -- Recursive query that references [members]
        SELECT
         H.shift_group_code,
         H.shift_code,
         CASE                  
             WHEN M.[path] LIKE '%' + CHAR(10) + CAST(H.shift_code AS varchar(max)) + CHAR(10) + '%'                  
             THEN 1                  
             ELSE 0              
         END AS isCycle,
         M.[path] + CAST(H.shift_code AS varchar(max)) + CHAR(10) AS [path]       
         FROM
         shift_grouping H       
         JOIN
         members M ON H.shift_group_code = M.shift_code  -- In this case, the join acts as the termination condition           
         WHERE 
        H.workspace_code IN ('default', 'test', 'test1')  
        AND M.isCycle = 0
         AND EXISTS (SELECT 1 FROM shift_group WHERE code = M.shift_code)    
     )    
     SELECT *       
     FROM shift S    
     WHERE 
        workspace_code IN ('default', 'test', 'test1')   
        AND ( 
            code = 'WS+DEFAULT' 
            OR EXISTS (
                     SELECT 1                    
                     FROM
                         members                         
                     WHERE
                         isCycle = 0 AND shift_code = S.code
             )
         )