如何防止 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
)
我有一个 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
)