Как предотвратить выполнение CTE, пока не достигнуто ИЛИ НЕ СУЩЕСТВУЕТ - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть запрос SQL Server, который использует некоторые CTE (общие выражения таблиц) . У него есть две таблицы, из которых он выбирает данные. Две таблицы идентичны по структуре, но не являются необходимыми данными. Сначала запрос будет выбран из table_a, а если не выбрано ни одной строки, он будет выбран из table_b. Запрос выглядит примерно так:

;WITH cte_a AS (
  ...
), cte_b AS (
  ...
) 
SELECT * 
FROM table_a
INNER JOIN cte_a ON condition_a
OR NOT EXISTS (
  SELECT *
  FROM table_b
  INNER JOIN cte_b ON condition_b
)

Текущая проблема, с которой я столкнулся, заключается в том, что cte_b всегда будет выполняться независимо от того, вернет ли table_a какие-либо строки. Это не очень идеально для меня;Я хотел бы, чтобы cte_b выполнялся тогда и только тогда, когда подзапрос для table_a не возвращает строк.

Я попытался переместить cte_b как раз перед подзапросом для table_b как

;WITH cte_a AS (
  ...
)
SELECT * 
FROM table_a
INNER JOIN cte_a ON condition_a
OR NOT EXISTS (
  ;WITH cte_b AS (
    ...
  ) 
  SELECT *
  FROM table_b
  INNER JOIN cte_b ON condition_b
)

Однако IDE жалуется. Я думаю, что это не тот способ, которым предполагается использовать CTE.

Ответы [ 4 ]

2 голосов
/ 06 ноября 2019

Создать временную таблицу для хранения данных - разбить запрос на два отдельных оператора INSERT, где второй выполняется только в том случае, если после завершения первого запроса данные не заполняются. Как то так:

CREATE TABLE #TEmp
(

);


;WITH cte_a AS (
  ...
)
INSERT INTO #TEmp
SELECT * 
FROM table_a
INNER JOIN cte_a ON condition_a

IF NOT EXISTS(SELECT 1 FROM #TEmp)
BEGIN;

INSERT INTO #TEmp
SELECT * 
FROM table_a
WHERE NOT EXISTS (
  SELECT *
  FROM table_b
  INNER JOIN cte_b ON condition_b
)
1 голос
/ 06 ноября 2019

Такова природа CTE.

Лучше всего было бы не использовать CTE и использовать объединение, но я полагаю, что вы не можете.

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

0 голосов
/ 06 ноября 2019
;WITH    cte1 AS
        (
        ....
        ),
        cte2 AS
        (
        ...
        )

SELECT * 
FROM table_a
INNER JOIN cte_a ON condition_a ---Choose Your Condition...

UNION ALL

SELECT *
FROM table_b
INNER JOIN cte_b ON condition_b ---Choose Your Condtion....
WHERE NOT EXISTS (SELECT * FROM cte2)

Примечание: -

За CTE должен следовать один оператор SELECT, INSERT, UPDATE, or DELETE, который ссылается на некоторые или все CTE columns.

0 голосов
/ 06 ноября 2019

Я бы сформулировал это, используя объединение, а затем исключая вторую половину объединения на cte_b, если первый CTE будет иметь какие-либо результаты.

;WITH cte_a AS (
    ...
),
cte_b AS (
    ...
)

SELECT * 
FROM table_a
INNER JOIN cte_a ON condition_a
UNION ALL
SELECT *
FROM table_b
INNER JOIN cte_b ON condition_b
WHERE NOT EXISTS (
    SELECT 1
    FROM table_a
    INNER JOIN cte_a ON condition_a
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...