SQL - ломать запрос - PullRequest
1 голос
/ 14 мая 2019

Я получил этот запрос из своего прежнего приложения, при выполнении которого слишком много времени занимает ответ. Поэтому я планирую разбить этот сложный запрос на несколько запросов и выполнить некоторые операции на стороне приложения, т.е. в более новом приложении.

 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 в начале большего запроса.

Или я не мог понять, как они объединяют members с shift_grouping.

Может ли кто-нибудь помочь мне с этим вопросом?

1 Ответ

1 голос
/ 14 мая 2019

Сложно оптимизировать этот запрос без дополнительных знаний о схеме базы данных, но он может помочь вам понять, что он делает.

Я также заменил пару условий IN на EXISTS, это даст вамдовольно высокая производительность, но я не думаю, что этого будет достаточно

. Члены - это Common Table Expression (CTE), который определяет временный набор результатов, когда сам его вызов называется Recursive CTE.

SHIFT_GROUPING представляется вашей таблицей иерархии, поэтому первый оператор SELECT определяет, где начинается CTE, а SELECT после UNION ALL определяет итерации

В общем, рекурсивный CTE состоит из трех частей:

  1. Начальный запрос, который возвращает базовый набор результатов CTE.Начальный запрос называется якорным членом.
  2. Рекурсивный запрос, который ссылается на общее табличное выражение, поэтому он называется рекурсивным членом.Рекурсивный член объединяется с якорным членом с помощью оператора UNION ALL.
  3. Условие завершения, указанное в рекурсивном элементе, которое завершает выполнение рекурсивного элемента.

Порядок выполнения рекурсивного CTE следующий:

  • Во-первых, выполните элемент привязки, чтобы сформировать базовый набор результатов (R0), используйте этот результат для следующей итерации.
  • Во-вторых, выполните рекурсивный элемент с набором входных результатов из предыдущей итерации (R-1) и возвращать набор результатов (Ri) до тех пор, пока не будет выполнено условие завершения.
  • В-третьих, объединить все наборы результатов R0, R1,… Rn, используя оператор UNION ALL для получения окончательного набора результатов..

     ;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
             )
         )
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...