0

我有一个遗留系统,其中数据使用“多级查询集”以树结构(稍后显示为树视图)加载。也就是说,每个级别都有自己的查询。下层依赖于上层检索到的数据。基本上,较低级别查询的参数是(一些)由较高级别查询返回的值。我能够检索查询,但我想使用“with”语句构建一个“通用”查询。问题是:如何在不使用连接修改查询的情况下在低级 CTE 中引用上级 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
4

1 回答 1

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 
于 2013-09-18T16:02:25.310 回答