如何实现第二个查询复用首个查询结果?含变量存储等问题
问题解答
1. 复用首个查询结果的操作术语
你这种把第一个查询嵌套在第二个查询的FROM子句中作为数据源的写法,专业术语叫做派生表(Derived Table),属于子查询的一种应用场景。
另外还有更清晰的替代方案:CTE(公共表表达式,Common Table Expression),用WITH关键字定义初始查询结果,后续可以直接复用,可读性更强,尤其适合多次复用的场景。
修正后的示例代码
派生表写法
SELECT column1, column2, column3, column4, column5, column6, ISNULL(NULLIF((column5 - column6), 0) / NULLIF(column5, 0), 0) * 100 AS columnGP FROM ( -- 这里是作为派生表的初始查询 SELECT column1, column2, column3, column4, SUM(column5) AS column5, SUM(column6) AS column6, TableB.column7 FROM TableA LEFT OUTER JOIN TableB ON TableB.column7 = TableA.column1 GROUP BY column1, column2, column3, column4, TableB.column7 -- 注意:非聚合列必须出现在GROUP BY中 ) AS InitialResults; -- 派生表必须指定别名
CTE写法
WITH InitialResults AS ( SELECT column1, column2, column3, column4, SUM(column5) AS column5, SUM(column6) AS column6, TableB.column7 FROM TableA LEFT OUTER JOIN TableB ON TableB.column7 = TableA.column1 GROUP BY column1, column2, column3, column4, TableB.column7 ) SELECT column1, column2, column3, column4, column5, column6, ISNULL(NULLIF((column5 - column6), 0) / NULLIF(column5, 0), 0) * 100 AS columnGP FROM InitialResults;
2. 查询结果存储为变量的相关问题
如何存储
根据结果的形态,有两种常用方式(以SQL Server为例,你的语法更贴合它):
- 单个值存普通变量:如果查询结果是单行单列的单个值,直接赋值即可:
DECLARE @TotalColumn5 DECIMAL(18,2); SELECT @TotalColumn5 = SUM(column5) FROM TableA; - 多行多列存表变量:如果是多行多列的结果,需要先定义表变量的结构,再插入数据:
-- 定义表变量结构 DECLARE @QueryResults TABLE ( column1 INT, column2 VARCHAR(50), column3 DATETIME, column4 INT, column5 DECIMAL(18,2), column6 DECIMAL(18,2), column7 INT ); -- 把初始查询结果插入表变量 INSERT INTO @QueryResults SELECT column1, column2, column3, column4, SUM(column5) AS column5, SUM(column6) AS column6, TableB.column7 FROM TableA LEFT OUTER JOIN TableB ON TableB.column7 = TableA.column1 GROUP BY column1, column2, column3, column4, TableB.column7; -- 后续直接查询表变量 SELECT column1, column2, column3, column4, column5, column6, ISNULL(NULLIF((column5 - column6), 0) / NULLIF(column5, 0), 0) * 100 AS columnGP FROM @QueryResults;
数据留存时长
- 普通变量和表变量:只在当前会话的脚本/存储过程执行周期内存在。脚本执行完毕、存储过程退出,或者会话断开后,变量会被立即销毁,数据随之消失。
- 如果你用临时表(
#TempTable)替代表变量:本地临时表(#开头)在会话结束时销毁;全局临时表(##开头)在所有引用它的会话都结束后才销毁。
性能影响
- 小数据量场景:几乎没有负面影响,反而能避免重复执行初始查询的开销,效率更高。
- 大数据量场景:表变量的统计信息有限,查询优化器可能生成不够高效的执行计划,这时用临时表会更优(临时表支持统计信息和索引)。
- 总体来说,只要根据数据量选择合适的存储方式,不会有显著的性能问题;错误选择(比如用表变量存几十万条数据)才可能导致性能下降。
内容的提问来源于stack exchange,提问作者Dave Hamilton
相关产品推荐
相关产品推荐

