我有一个遗留系统,其中使用“多级查询”将数据加载到树结构中(稍后显示为树视图)。也就是说,每个级别都有自己的查询。较低级别取决于上级检索的数据。基本上,较低级别查询的参数是(某些)上级查询返回的值。我能够检索查询,但我想使用“with”语句构建一个“常规”查询。问题是:如何在不使用连接修改查询的情况下引用较低级别的CTE?
以下是我想要的简化示例:
with Level1Q as (select * from table1),
Level2Q as (select * from table2 where id=Level1Q.id)
select * from Level2Q
我可以单独访问每个查询,因为它们存储在XML文件中,该文件因用户而异:select * from table1
& select * from table2 where id=:param1
。我已经有了“填充”参数的例程但我不想通过插入连接来更改现有的查询文本,因为这意味着解析SQL语法的相对复杂的过程。
这就是我所知道的,并尽量避免:
with Level1Q as (select * from table1),
Level2Q as (select t2.* from table2 t2, Level1Q l1 where t2.id=l1.id)
select * from Level2Q
答案 0 :(得分:1)
她对我如何处理这个问题的模糊概述。它做了很多假设,缺少关键组件,没有以任何方式进行调试,并且完全依赖于那些你无法控制对于难以确定的值“好”的查询好的。
假设:一组看起来像这样的查询:
Level1Q: select * from users where name=:param_user
Level2Q: select * from projects where id=:param_id
Level3Q: select * from details where id=:param_id
Level4Q: <etc>
因此,对于“3级”查询,您需要生成以下内容:
;WITH
Level1Q as (select * from users where name=:param_user)
,Level2Q as (select * from projects where id=:param_id)
,Level3Q as (select * from details where id=:param_id)
select * from Level3Q
这或类似的东西应该产生该查询:
DECLARE
@Command nvarchar(max)
,@Query nvarchar(max)
,@Loop int
,@MaxDepth int
,@CRLF char(2) = char(13) + char(10) -- Makes the dynamic code more legible
SET @Command = 'WITH'
-- Set @MaxDepth to the level you want to query at
SET @MaxDepth = 3
SET @Loop = 0
WHILE @Loop < @MaxDepth
BEGIN
SET @Loop = @Looop + 1
-- Get the query for this level
SET @Query = <next query>
SET @Command = replace(@Command + @CRLF
+ case @Loop when 1 then ' ' else ' ,' end
+ 'Level<<@Loop>>Q as (' + @Query + ')'
,':param_user', <appropriate value) -- Only used when @Loop = 1
,':param_id', 'Level<<@Loop>>Q.id') -- This assumes the link to the prior query is always by a column named "id"
,'<<@Loop>>', @Loop) -- Done last, as the prior replace added another <<@Loop>>
END
-- Add the final pull
SET @Command = @Command + @CRLF + replace(' select * from Level<<@Loop>>Q', '<<@Loop>>', @Loop - 1)
-- The most important command, because debugging this mess will be a pain
PRINT @Command
--EXECUTE sp_executeSQL @Command