Sql 为什么我从这个查询中得到了错误的输出?
我试图在ms sql server中分页结果,但在获得正确结果时遇到了一些问题。我希望获得与mysql:s LIMIT相同的结果,我正尝试使用此模型来实现这一点:Sql 为什么我从这个查询中得到了错误的输出?,sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,我试图在ms sql server中分页结果,但在获得正确结果时遇到了一些问题。我希望获得与mysql:s LIMIT相同的结果,我正尝试使用此模型来实现这一点: SELECT * FROM ( SELECT TOP x * FROM ( SELECT TOP y fields FROM table WHERE conditions ORDER BY table.field ASC) as foo ORDER by
SELECT * FROM (
SELECT TOP x * FROM (
SELECT TOP y fields
FROM table
WHERE conditions
ORDER BY table.field ASC) as foo
ORDER by field DESC) as bar
ORDER by field ASC
发件人:
列出前30行的原始查询如下所示:
SELECT TOP 30 pt.[BSNR], t.ID, pt.RESDATUMTID, pt.LAND1, pt.HPL1, pt.ANKDATUMTID, pt.LAND2, pt.HPL2
FROM [statistik2].[dbo].[ttrip] AS t
JOIN [statistik2].[dbo].[tparttrip] AS pt
ON t.ID = pt.TRIP_ID
WHERE t.DBKRDAT > '2012-06-27'
ORDER BY pt.BSNR DESC, t.ID, pt.RESDATUMTID
我的尝试是:
SELECT * FROM (
SELECT TOP 10 * FROM (
SELECT TOP 30 pt.ID AS PTID, pt.[BSNR], t.ID, pt.RESDATUMTID, pt.LAND1, pt.HPL1, pt.ANKDATUMTID, pt.LAND2, pt.HPL2
FROM [statistik2].[dbo].[ttrip] AS t
JOIN [statistik2].[dbo].[tparttrip] AS pt
ON t.ID = pt.TRIP_ID
WHERE t.DBKRDAT > '2012-06-27'
ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
) as pttt
ORDER BY pttt.PTID DESC) AS ptttt
ORDER BY ptttt.PTID
查询的输出:
有人能解释一下我做错了什么吗?请注意示例查询 最里面的子查询按
字段ASC
对结果进行排序。这是所有页面的主要顺序。最里面的子查询按该顺序获取顶部的y
行
中间层子查询颠倒顺序,从上一个结果中获取顶部x
行,从而有效地获取整个数据集顶部y
行的底部x
行
主查询只是重新建立行的主顺序
你也应该这样做。最内层的查询按如下顺序排列行:
ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
ORDER BY pt.BSNR ASC, t.ID ASC, pt.RESDATUMTID DESC
如果这是您的主行顺序,那么您应该在中间层子查询中使用它的反转版本,例如:
ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
ORDER BY pt.BSNR ASC, t.ID ASC, pt.RESDATUMTID DESC
在主查询中如何对行进行排序可能并不重要,但我会遵循示例并再次颠倒顺序,使其与最内部查询的顺序相匹配。您可以使用ROW_NUMBER()获取运行计数-这使分页更容易…例如
(注意:这适用于SQL 2005及以上版本-SQL 2000不支持row_number()函数)
假设一个表有一列“Name”:
SELECT * FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY Name) as RunningVal, * FROM Names
) as Running
WHERE RunningVal BETWEEN 5 AND 10
老实说,整个三重分类有点老派:p
在您的情况下,它将类似于:
SELECT * FROM (
SELECT TOP 30
ROW_NUMBER() OVER (ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID) as RunningVal,
pt.ID AS PTID,
pt.[BSNR],
t.ID,
pt.RESDATUMTID,
pt.LAND1,
pt.HPL1,
pt.ANKDATUMTID,
pt.LAND2,
pt.HPL2
FROM [statistik2].[dbo].[ttrip] AS t
JOIN [statistik2].[dbo].[tparttrip] AS pt
ON t.ID = pt.TRIP_ID
WHERE t.DBKRDAT > '2012-06-27'
ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
) as Running
WHERE RunningVal BETWEEN 1 AND 10
事实上,您甚至可以去掉内部顶部,只需使用:
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID) as RunningVal,
pt.ID AS PTID,
pt.[BSNR],
t.ID,
pt.RESDATUMTID,
pt.LAND1,
pt.HPL1,
pt.ANKDATUMTID,
pt.LAND2,
pt.HPL2
FROM [statistik2].[dbo].[ttrip] AS t
JOIN [statistik2].[dbo].[tparttrip] AS pt
ON t.ID = pt.TRIP_ID
WHERE t.DBKRDAT > '2012-06-27'
ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
) as Running
WHERE RunningVal BETWEEN @x AND @y
其中@x是下限,@y是上限(介于两者之间,且行数()从1开始,因此x=1和y=10将给出记录1-10)
编辑:不确定在MySql中指定超出范围的偏移量时会发生什么(据我所知,官方文档似乎没有提到这一点),但请注意,如果指定@x=100和@y=110,并且表中只有50条记录,则不会得到任何结果
Edit2:如果你想修改它,就添加了一个sqlfiddle链接
什么版本的SQL?如果您使用的是MSSQL 2005+,则可以使用(按xxxx排序)上的行数()来获取运行计数,然后使用此函数来创建类似于MySql的LIMIT XX、XXIt的MSSQL 2008的函数,所以也许我应该尝试一下!谢谢我已经添加了一个答案——我将看看是否可以用您需要的查询更新它。有些人因为SQL产品的旧版本而不得不坚持老一套。不过,OP的DBMS很可能是SQL Server 2005或更高版本,但提及
行号()所需的最低版本不会对您的答案造成丝毫影响。:)啊已经在评论中问了这个问题-无论如何都会更新答案!再次感谢,我很感激,它看起来干净多了!