【发布时间】:2009-12-16 16:47:20
【问题描述】:
我们以程序方式生成大量 SQL,而 SQL Server 正在扼杀我们。由于elsewhere 记录的一些问题,我们基本上会选择 TOP 2 ** 32 而不是 TOP 100 PERCENT。
注意:我们必须使用子查询。
这是我们的查询:
SELECT * FROM (
SELECT [me].*, ROW_NUMBER() OVER( ORDER BY (SELECT(1)) )
AS rno__row__index FROM (
SELECT [me].[id], [me].[status] FROM (
SELECT TOP 4294967296 [me].[id], [me].[status] FROM
[PurchaseOrders] [me]
LEFT JOIN [POLineItems] [line_items]
ON [line_items].[id] = [me].[id]
WHERE ( [line_items].[part_id] = ? )
ORDER BY [me].[id] ASC
) [me]
) [me]
) rno_subq
WHERE rno__row__index BETWEEN 1 AND 25
有没有更好的方法可以做到这一点,任何人都可以看到?
更新:这里是对整个子查询问题的一些说明:
我的问题的关键词是“程序上”。我需要能够可靠地封装结果集,以便它们可以像构建块一样堆叠在一起。例如,我想获取按制作它们的艺术家的姓名排序的前 10 张 cd,并获取每张 cd 的相关艺术家。我所做的是组装一个整体子选择,表示按加入的艺术家姓名排序的 cd,然后对其应用限制,然后将嵌套的子选择连接到艺术家表,然后才执行结果查询。隔离是必要的,因为请求订购的 cd 的代码与选择前 10 名 cd 的代码无关且忽略了,而后者又与请求相关艺术家的代码无关且忽略了。
现在您可能会说我可以将内部 ORDER BY 移动到 OVER() 子句中,但随后我破坏了封装,因为我必须选择连接表的列,以便稍后按它们排序。另一个问题是在一个别名下合并两个表。如果我在两个表中都有相同名称的列,则 select me.* 将在此停止并出现列名不明确的错误。
我愿意牺牲一点优化器的性能,但 2**32 对我来说似乎太过分了。所以我正在寻找中间立场。
【问题讨论】:
-
您使用 TOP 有什么特别的原因吗?
-
IIRC,内部 ORDER BY 需要 TOP 才能工作。否则 SQL Server 会引发关于 ORDER BY 在子查询中无效的错误。
-
好的。当你说你必须使用子查询时,这是否意味着你必须使用两个嵌套查询,或者至少 1 个?因为你绝对可以消除其中一个。
-
我复制了您的代码并对我们的一些表运行了等效的代码,在 SQL Server 2005 下,它运行得非常高效 - 它在一秒钟内返回了 190 万条记录中的前 25 条。那么这个问题只是关于代码,而不是性能?
-
ORDER BY only 如果应用于 final(即 outer) 选择。内部 ORDER BY 仅适用于 TOP 计数,它们的 ORDER NOT 保证保留在外部 SELECT 中。
标签: sql sql-server orm