简体   繁体   English

一个查询中的多个 SELECT 使用相同的 WITH

[英]Multiple SELECTs in one query using same WITH

This query filters some IDs from a master table, and returns all data abpout that IDs from two other tables as two record sets:此查询过滤主表中的一些 ID,并将来自其他两个表的 ID 作为两个记录集返回所有数据 abpout:

WITH filteredIds (fid) AS 
(
    SELECT id 
    FROM MasterTable 
    WHERE <somecondition>
)
SELECT * 
FROM Table1 
RIGHT JOIN filteredIds ON (Table1.id = filteredIds.fid);

WITH filteredIds (fid) AS 
(
    SELECT id 
    FROM MasterTable 
    WHERE <somecondition>
)
SELECT * 
FROM Table2 
RIGHT JOIN filteredIds ON (Table2.id = filteredIds.fid);

This works so far, but it would be great to have just one WITH clause, since the condition is always the same.到目前为止,这是可行的,但最好只有一个 WITH 子句,因为条件总是相同的。 Further more, the condition is often written manually, since this is used to collect some diagnostics data.此外,条件通常是手动编写的,因为它用于收集一些诊断数据。

But this但是这个

WITH filteredIds (fid) AS 
(
    SELECT id 
    FROM MasterTable 
    WHERE <somecondition>
)
SELECT * 
FROM Table1 
RIGHT JOIN filteredIds ON (Table1.id = filteredIds.fid);

SELECT * 
FROM Table2 
RIGHT JOIN filteredIds ON (Table2.id = filteredIds.fid);

does not work, SQL Server claims it does not know object filteredIds in the last query.不起作用,SQL 服务器在最后一个查询中声称它不知道filteredIds

Have I overseen something, or doesn't it work that way?我是否监督了某些事情,或者它不是那样工作的? I guess the alternative would be a temporary table.我想替代方案将是一个临时表。

Once a CTE has been consumed in a query, it cannot be reused in another query.一旦在查询中使用了 CTE,就不能在另一个查询中重用它。 There is no direct workaround as far as I know.据我所知,没有直接的解决方法。 The closest thing perhaps to want you want would be to create a bona fide temporary table:最接近您想要的可能是创建一个真正的临时表:

CREATE TABLE #temp (fid int);
INSERT INTO #temp (fid)
SELECT id FROM MasterTable WHERE <somecondition>;

Then, you may reuse the temporary table directly:然后,您可以直接重用临时表:

SELECT * FROM Table1 a RIGHT JOIN #temp b ON a.id = b.fid;
SELECT * FROM Table2 a RIGHT JOIN #temp b ON a.id = b.fid;

You can't do what you want with CTE.你不能用 CTE 做你想做的事。 CTE doesn't exist outside the query where it was defined. CTE 在定义它的查询之外不存在。

I think that the closest thing to what you want is called a "view".我认为最接近您想要的东西称为“视图”。

CREATE VIEW filteredIds
AS
SELECT id AS fid
FROM MasterTable 
WHERE <somecondition>
;

And now you can use that view in many other queries.现在您可以在许多其他查询中使用该视图。

SELECT * 
FROM Table1 
RIGHT JOIN filteredIds ON (Table1.id = filteredIds.fid);

SELECT * 
FROM Table2 
RIGHT JOIN filteredIds ON (Table2.id = filteredIds.fid);

Furthermore, in SQL Server it will work exactly like a CTE in a sense that the list of filtered IDs is not materialized and the engine will optimize the whole query that references the view.此外,在 SQL 服务器中,它的工作方式与 CTE 完全相同,因为过滤的 ID 列表没有具体化,引擎将优化引用视图的整个查询。 It will inline the view definition into the outer / main query as if you wrote everything in one big query.它将视图定义内联到外部/主查询中,就像您在一个大查询中编写所有内容一样。 Just like it would do with CTE.就像它对 CTE 所做的那样。

With a temporary table you explicitly write this temporary result to disk and read it back.使用临时表,您可以将此临时结果显式写入磁盘并将其读回。

In some cases it may be better, in some not.在某些情况下它可能会更好,在某些情况下则不然。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM