настройка сложных SQL-запросов - PullRequest
1 голос
/ 29 мая 2019

Здравствуйте, у меня есть запрос, который занимает много времени для выполнения и потребляет столько ресурсов, запрос похож на этот:

WITH first_match AS (
        SELECT t1.name
               , t1.lastname
               , t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2 
        ON t1.name = t2.name
)
, second_match AS (
        SELECT t1.name
                , t1.lastname
                , t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2
        ON t1.name = SUBSTR(t2.name,0,INSTR(t2.name,'-'))
        WHERE REGEXP_LIKE(t2.name,'[-]')
        AND (t1.name, t1.lastname) NOT IN (SELECT name, lastname FROM first_match)
)
, third_match AS (
        SELECT t1.name
                ,t1.lastname
                ,t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2
        ON t1.name = REGEXP_REPLACE(t2.name, 'uselesssuffix', '')
        WHERE REGEXP_LIKE(t1.name, 'uselesssuffix')
        AND (t1.name, t1.lastname) NOT IN (
                                SELECT name, lastname FROM first_match
                                UNION
                                SELECT name, lastname FROM second_match
                                )
)
, fourth_match AS (
        SELECT t1.name
                ,t1.lastname
                ,t2.location
        FROM table1 t1
        INNER JOIN
        table2 t2
        ON t1.name = SUBSTR(t2.name, 0, 7)
        WHERE LENGTH(t2.name) > 6
        AND (t1.name, t1.lastname) NOT IN (
                                SELECT name, lastname FROM first_match
                                UNION
                                SELECT name, lastname FROM second_match
                                UNION
                                SELECT name, lastname FROM third_match
                                )
)
, final_result AS (
SELECT * FROM first_match
UNION
SELECT * FROM second_match
UNION
SELECT * FROM third_match
UNION
SELECT * FROM fourth_match
)
SELECT * FROM final_result;

Где у меня есть две таблицы и я пытаюсь соединить их между собойскажем, 4 возможных условия, первый CTE содержит результат первого условия, второй содержит записи, не включенные в первое и соответствующие второму условию, третье содержит остальные, которые также соответствуют третьему условию и т. д.использование условия AND (t1.name, t1.lastname) NOT IN (SELECT name, lastname FROM first_match).. и, в конечном итоге, я использую UNION для генерации окончательного результата, теперь это относительно большое количество CTE (в данном случае 5) и большое количество UNION, и условия превращают этот запрос в тяжелый ивыполнение требует так много ресурсов и так много времени, любые идеи о том, есть ли лучший способ реализовать тот же сценарий, но с другим подходом, возможно, в одном CTE

Ответы [ 2 ]

1 голос
/ 11 июня 2019

Я что-то здесь не так?

В сложном объединении, включающем несколько логических выражений ИЛИ-ed вместе, оценка останавливается с первым выражением из тех, которые оцениваются как ИСТИНА.

Так почему не это?

    SELECT   t1.name
           , t1.lastname
           , t2.location
    FROM table1 t1
    INNER JOIN
    table2 t2 
    ON t1.name = t2.name
    OR  (    -- REGEXP_LIKE(t2.name,'[-]')
             -- AND t1.name = SUBSTR(t2.name,1,INSTR(t2.name,'-')-1)
         t1.name=SPLIT_PART(t2.name,'-',1)
    )
    OR  (    -- REGEXP_LIKE(t1.name, 'uselesssuffix') 
             -- AND t1.name = REGEXP_REPLACE(t2.name, 'uselesssuffix', '')
         t1.name=SPLIT_PART(t2.name,'uselesssuffix',1)
    )
    OR  (    LENGTH(t2.name) > 6
         AND t1.name = SUBSTR(t2.name, 1, 7)
    )

.. и пока я занимался этим, я пытался уменьшить количество необходимых вызовов функций ...

И в Vertica функция SUBSTR () начинается с 1-й, а не с 0-й позиции строки ..: -]

0 голосов
/ 29 мая 2019

У вас есть несколько совпадений, которые вы пытаетесь расставить по приоритетам.Следует попробовать серию из LEFT JOIN s:

SELECT t1.name, t1.lastname,
       COALESCE(t2_1.location, t2_2.location, , . . . )
FROM table1 t1 LEFT JOIN
     table2 t2_1 
     ON t1.name = t2_1.name LEFT JOIN
     table2 t2_2
     ON t1.name = SUBSTR(t2_2.name, 1, INSTR(t2_2.name, '-')) AND
        t2_2.name LIKE '%-%' AND
        t2_1.name IS NULL LEFT JOIN
     table2 t2_3
     ON t1.name = REGEXP_REPLACE(t2_3.name, 'uselesssuffix', '') AND
        t1.name LIKE '%uselesssuffix%' AND
        t2_1.name IS NULL AND
        t2_2.name IS NULL LEFT JOIN
     . . .
WHERE t1.name IS NOT NULL OR
      t2_1.name IS NOT NULL OR
      . . . 

Обратите внимание, что каждое новое условие проверяет, что все предыдущие условия не совпадают.

...