如何防止 CTE 执行直到达到或不存在

How to prevent CTE execution until reached OR NOT EXISTS

我有一个 SQL 服务器查询,它使用了一些 CTEs (Common Table Expressions)。它有两个表,它 select 从中获取数据。两张表结构完全相同,只是没有必要的数据。查询将首先从 table_a 中获取 select,如果没有获取任何行,那么它会从 table_b 中获取 selects。查询是这样的:

;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
)

我目前遇到的问题是,无论 table_a returns 是否有任何行,cte_b 总是会被执行。这对我来说不是很理想;我想让 cte_b 当且仅当 table_a returns 的子查询没有行时才执行。

我尝试将 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 的方式。

如果第一个 CTE 有任何结果,我会使用联合来表达这一点,然后在 cte_b 上排除联合的后半部分。

;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
)

这就是 CTE 的本质。

最好的办法是不使用 CTE 而使用连接,但我认为你不能。

我建议您尝试使用子查询,以便引擎可以一次处理所有内容。

;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 后面必须跟一个引用部分或全部 CTE columns.

的单个 SELECT, INSERT, UPDATE, or DELETE 语句

创建临时 table 用于存储数据 - 将查询拆分为两个单独的 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
)