我有一个程序可以生成一些标准SQL,例如SELECT * FROM TEST ORDER BY X
并将它(作为一个字符串)传递给一个函数以及一个整数来创建一个有限的查询(也是一个字符串)。对于Oracle(针对该应用程序开发),此函数返回SELECT * FROM (
sq ) WHERE ROWNUM <=
n给出:
SELECT * FROM (SELECT * FROM TEST ORDER BY X) WHERE ROWNUM <= 10
有效。
不幸的是,我无法弄清楚如何编写Microsoft SQL Server的等效函数(我不是MS SQL专家)。
我试过了:
SELECT TOP 10 FROM (SELECT * FROM TEST ORDER BY X)
但这导致:
Error: Incorrect syntax near the keyword 'from'.
然后我尝试了:
SELECT TOP 10 * FROM (SELECT * FROM TEST ORDER BY X)
让我获得了:
Error: The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP or FOR XML is also specified.
这令人沮丧,因为我指的是TOP ....
我尝试了一些其他的霰弹枪变种,包括:
SELECT TOP (10) * FROM (SELECT * FROM TEST ORDER BY X)
SELECT TOP 10 * FROM (SELECT * FROM TEST ORDER BY X) SUBQUERY
SELECT TOP 10 * FROM (SELECT * FROM TEST ORDER BY X) AS SUBQUERY
SELECT * FROM (SELECT * FROM TEST ORDER BY X) WHERE ROW_NUMBER <= 10
但当然,它们都不起作用。
根本没有希望吗?
答案 0 :(得分:4)
使用SET ROWCOUNT。这使得工作变得非常简单。
SET ROWCOUNT 10
SELECT * FROM [TEST] ORDER BY [X]
SET ROWCOUNT 0
答案 1 :(得分:2)
您可以在此处正确使用CTE(公用表格式)和排名函数。
; WITH CTE_RowNumbers AS
(
SELECT *, RANK() OVER (ORDER BY X) AS ROWNUM FROM Users
)
SELECT * FROM CTE_RowNumbers WHERE ROWNUM < 10;
只需用变量替换10。
这将在MS SQL中提供与从Oracle中的ROWNUM函数获得的结果完全相同的结果。
请注意:此代码段中的ROWNUM只是一个别名,而不是MSSQL中的函数,真正的功能在于使用公共表表达式和使用的排名函数。
更新:蒙面CTE - 用变量替换[VAR-Name]
; WITH CTE_RowNumbers AS
(
SELECT [VAR-ColumnList], RANK() OVER (ORDER BY [VAR-OrderByList]) AS ROWNUM FROM [VAR-Table]
)
SELECT [VAR-ColumnList] FROM CTE_RowNumbers WHERE ROWNUM < [VAR-ResultSize];
从查询中提取输入变量:
SELECT [VAR-ColumnList] FROM [VAR-Table] ORDER BY [VAR-OrderByList]
您还需要为[VAR-ResultSize]指定一个值,它的外观是不变的并且在您的函数中设置了?
注意:如果您需要在订单中添加DESC或ASC,可以提供更大的灵活性,只需扩展您的脚本并将其作为变量包含在内。
答案 2 :(得分:1)
子查询是集合,因此是无序的,因此除非您还使用ORDER BY
,否则不能将它们与TOP
一起使用。
如果要限制返回的行数,并且不关心它们是哪些行,则可以编辑任何内部ORDER BY
(如果有的话),然后为子查询提供别名
原始查询:
SELECT * FROM TEST ORDER BY X
编辑并包装以返回10行:
SELECT TOP 10 * FROM (SELECT * FROM TEST) AS EXPR
或者您可以将TOP子句应用于子查询:
SELECT TOP 10 * FROM (SELECT TOP 10 * FROM TEST ORDER BY X) AS EXPR
不幸的是,这不能保证返回与:
相同的结果SELECT TOP 10 * FROM TEST ORDER BY X
为此,您需要在子查询之外移动ORDER BY:
SELECT TOP 10 * FROM (SELECT * FROM TEST) AS EXPR ORDER BY X
您还可以参数化要返回的行数:
SELECT TOP (@nrows) * FROM (SELECT * FROM TEST) AS EXPR
使用SQL Server 2012,您几乎可以实现您真正追求的目标,除非在这种情况下需要ORDER BY
:
SELECT * FROM TEST ORDER BY X OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY
答案 3 :(得分:0)
您可以尝试临时表:
select * into #temp from test order by x
select top 10 * from #temp where ...
答案 4 :(得分:0)
我认为这就是你要找的东西(我假设是SQL Server 2005及以上版本):
SELECT * FROM
(SELECT *,ROW_NUMBER() OVER (ORDER BY x) rownum FROM test) tmp
WHERE rownum BETWEEN 1 AND 10
其中'x'是要排序的列,并'测试'要从中选择的表。此外,'count'列通常也可用于返回,尤其是在您进行分页时:
SELECT * FROM
(SELECT *,COUNT(*) OVER() cnt,ROW_NUMBER() OVER (ORDER BY x) rownum FROM test) tmp
WHERE rownum BETWEEN 1 AND 10
答案 5 :(得分:-1)
做一件非常简单直接的事情: - &gt;&gt;
例如:SELECT TOP 10 * FROM(SELECT * FROM TEST)AS X