我试图在ms sql server中分页结果,我遇到了一些麻烦,得到了正确的结果。我想获得与mysql相同的结果:s LIMIT和Iäm试图使用这个模型来做到这一点:
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
来自:http://josephlindsay.com/archives/2005/05/27/paging-results-in-ms-sql-server/
列出前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
查询的输出:http://speedy.sh/5NQeq/sqloutput.txt
有人可以解释我做错了吗?
答案 0 :(得分:2)
您可以使用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
事实上你甚至可以摆脱内在的TOP并使用:
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是上限(BETWEEN是包含的,ROW_NUMBER()从1开始,因此x = 1,y = 10将为您提供记录1-10)
编辑:当你在LIMIT中指定超出范围的OFFSET时,不确定在MySql中会发生什么(据我所知,官方文档似乎没有提到这个) ,但要小心,如果你指定@x = 100和@y = 110并且表中只有50条记录,你将得不到任何结果
Edit2:如果你想改进它,可以添加一个SQL小提琴链接!
答案 1 :(得分:1)
注意示例查询。
最里面的子查询按field ASC
对结果进行排序。这是所有页面的主要顺序。最里面的子查询按顺序排列前y
行。
中间层子查询反转订单并从前一个结果中获取前x
行,从而有效地获取底部x
整个数据集的顶部y
行的行。
主查询只是重新建立行的主要顺序。
你应该这样做。您最内层的查询会按如下顺序排序:
ORDER BY pt.BSNR DESC, t.ID DESC, pt.RESDATUMTID
如果这是你的主要行顺序,那么你应该在你的中间层子查询中使用它的反转版本,例如:
ORDER BY pt.BSNR ASC, t.ID ASC, pt.RESDATUMTID DESC
在主查询中排序行的方式可能并不重要,但我会按照示例重新颠倒顺序,使其与最里面的查询匹配。