将值传递给派生表

Posted

技术标签:

【中文标题】将值传递给派生表【英文标题】:Pass Value To Derived Table 【发布时间】:2012-07-25 12:36:36 【问题描述】:

有没有办法查询?

在派生表中,我想从外部查询中引用一个值 ([docSVsys].[sID])

我得到一个错误:

Msg 4104, Level 16, State 1, Line 7 多部分标识符 无法绑定“docSVsys.sID”。

是的,我知道这个查询可以简化为无循环。 有一个游标必须循环并尝试将其转换为如此设置。

select top 10 [docSVsys].[sID], [sI].[count]
from docSVsys 
join 
(
    select count(*) as [count]   
    from docSVenum1 as [sIt]
    where  [sIt].[sID] = [docSVsys].[sID] 
) as [sI] 
on  '1' = '1'
order by [docSVsys].[sID]

交叉应用似乎可以解决问题。 它比游标版本快 1/3。 下面使用交叉应用的真实查询。

SELECT [sO].[sID], [sI].[max], [sI].[avg], [sI].[stdev]
FROM docSVsys as [sO] with (nolock)
cross apply 
( 
    select [sO].[sID], max(list.match) as 'max', avg(list.match) as 'avg', stdev(list.match) as 'stdev'
    from
    (
        select #SampleSet.[sID], [match] = 200 * count(*) / CAST ( #SampleSetSummary.[count] + [sO].[textUniqueWordCount]  as numeric(8,0) ) 
        from #SampleSet with (nolock) 
        join FTSindexWordOnce as [match] with (nolock) -- this is current @sID
            on match.wordID  = #SampleSet.wordID
            and [match].[sID] = [sO].[sID]
        join #SampleSetSummary with (nolock)  -- to get the word count from the sample set
            on #SampleSetSummary.[sID] = #SampleSet.[sID] 
        group by #SampleSet.[sID], #SampleSetSummary.[count] 
    ) as list
    having max(list.match) > 60 
) as [sI]  
where [textUniqueWordCount] is not null and [textUniqueWordCount] > 4 and [sO].[sID] <= 10686
order by [sO].[sID]

【问题讨论】:

【参考方案1】:

你可以用 CROSS APPLY 而不是 JOIN 做你想做的事:

select top 10 [docSVsys].[sID], [sI].[count] 
from docSVsys  
cross apply 
( 
    select count(*) as [count]    
    from docSVenum1 as [sIt] 
    where  [sIt].[sID] = [docSVsys].[sID]  
) as [sI]  
order by [docSVsys].[sID] 

【讨论】:

是的,它是以循环方式实现的,但这正是我们所要求的。它是否比通过查询的分组连接执行得更好取决于表、索引等的大小。另一种选择可能是将分组查询执行到临时表中,以便您可以在 sID 上建立索引。我会说测试各种选项并使用性能最佳的选项。 太棒了,现在我得到了交叉申请 太好了。有些人认为它仅适用于表值函数,但它也可以用于引用先前表中的列的任意查询。【参考方案2】:

将 ID 添加到派生表中,然后加入该表:

select top 10 [docSVsys].[sID], [sI].[count]
from docSVsys 
join 
(
     select [sIt].[sID], count(*) as [count]   
     from docSVenum1 as [sIt]
     group by [sIt].[sID]
) as [sI] 
on [sI].[sID] = [docSVsys].[sID] 
order by [docSVsys].[sID]

【讨论】:

是的,这是替代语法。但我绝对必须一次循环一个 [docSVsys].[sID]。在现实生活中,如果该内部循环生成所有行一次,它将是几个 TB。该内部循环一次评估大约 1 M 行以生成一个输出行。并且内部循环被调用了大约 1 M 次。这可能只是停留在光标上。作为游标,它运行 8 小时(内存占用很小)。

以上是关于将值传递给派生表的主要内容,如果未能解决你的问题,请参考以下文章

将DataTable传递给存储过程中的表值参数不起作用[关闭]

在使用表值参数时如何将多个参数一起传递给存储过程

关于将值传递给方法的困惑? [复制]

如何使用 JDBC 将表值参数(类数组参数)传递给 Microsoft SQL Server 2008 R2 中的存储过程? [复制]

无法正确地将值从父母传递给孩子和孩子传递给父母

AngularJS - 将值传递给组件