MS 访问限制 X、Y
Posted
技术标签:
【中文标题】MS 访问限制 X、Y【英文标题】:MS Access LIMIT X, Y 【发布时间】:2011-12-24 21:46:11 【问题描述】:是否可以模拟以下 mysql 查询:
SELECT * FROM `tbl` ORDER BY `date` DESC LIMIT X, 10
(X是参数)
在 MS Access 中?
【问题讨论】:
【参考方案1】:虽然 Access/JET TOP
关键字不直接提供 OFFSET
功能,但我们可以使用 TOP
、子查询和“派生表”的巧妙组合来获得相同的结果。
这是一个示例,用于在ORDER BY
Name 和 Id 的 Person 表中从偏移量 20 开始获取 10 行。 .
SELECT Person.*
FROM Person
WHERE Person.Id In
(
SELECT TOP 10 A.Id
FROM [
SELECT TOP 30 Person.Name, Person.Id
FROM Person
ORDER BY Person.Name, Person.Id
]. AS A
ORDER BY A.Name DESC, A.Id DESC
)
ORDER BY Person.Name, Person.Id;
本质上,我们查询前 30 个,倒序,查询前 10 个,然后从表中选择匹配的行,再次按正序排序。这应该是相当有效的,假设 Id 是 PRIMARY KEY
,并且 Name 上有一个索引。可能需要针对 Name、Id(而不是仅针对 Name)的特定覆盖索引以获得最佳性能,但我认为索引隐含地覆盖了PRIMARY KEY
。
【讨论】:
但是考虑到限制是 10 并且有 11 行,偏移量 10 实际上会返回除第一行之外的所有行 (10)。所以它与队列机制非常相似——你只需弹出第一个元素,最后一个被推送。但想法是在偏移量为 10 时仅显示一个(最后)行,而您的查询不会这样做。【参考方案2】:另一种方式 - 假设您希望在一个名为 table1 的表中包含 1000 到 1999 条记录(当然,如果您有那么多记录),您可以这样做。
MSSQL
SELECT *
FROM table1 LIMIT 1000, 1999;
MS 访问
SELECT TOP 1000 *
FROM table1
Where ID NOT IN (SELECT TOP 999 table1.ID FROM table1);
分解一下
SELECT TOP NumA *
FROM table1
Where ID NOT IN (SELECT TOP NumB table1.ID FROM table1);
UpperLimit = 1999
LowerLimit = 1000
NumA = UpperLimit - LowerLimit + 1
例如。 1000 = 1999 - 1000 + 1
NumB = LowerLimit -1
例如。 999 = 1000 - 1
【讨论】:
【参考方案3】:更好的查询是:
SELECT Users.*
FROM Users
WHERE Users.id In
(
SELECT TOP X A.id
FROM [
SELECT TOP Y Users.*
FROM Users
ORDER BY Users.reg_date DESC
]. AS A
ORDER BY A.reg_date ASC
)
ORDER BY Users.reg_date DESC
在哪里
if((totalrows - offset) < limit) then
X = (totalrows - offset)
else
X = limit
还有:
Y = limit + offset
例如,如果 total_rows = 12,我们将 limit 设置为 10(每页显示 10 个用户),并且 limit strong>offset 计算为 p * limit - (limit) 其中 p 是当前页面的编号,因此在第一页 ( p = 1) 我们将得到:X = 12 和 Y = 10,在第二个 X = 2 和 >Y = 20。用户列表按注册日期排序(降序)。
【讨论】:
当使用 TOP 进行分页时,最好在排序中包含主键作为决胜局并确保可预测的排序。 看起来不错,除了我认为 X 应该是限制的最大值或(total_count - 偏移量)。否则,除非您查询最后一页,否则您最终会得到比预期更多的结果行。 @Steve Jorgensen 关于主键 - 你是完全正确的。我只是想为自己简化对这个“技巧”的理解。X
评论怎么样 - 我不太明白你在这里。这很好,因为如果我们以我发布的示例为例,最后一页(page = 2)的查询将是SELECT TOP 2
以上SELECT TOP 20
,实际上只会给您预期的两个结果。它永远不会重复前几页中的行,因为它是由total_rows - offset
计算的。所以对我来说一切都很好。
X 计算的问题是当您不在最后一页时会发生什么。如果您总共有 35 行,并且您希望 offset=11,limit=10,那么使用 X 和 Y 的规则,X 将为 24,Y 将为 21。结果,您将返回 21 行。 X 仅应为 total_count - 偏移量,当该数字
@Steve Jorgensen - 哦,对不起,你是对的。我选择你的答案是最好的,因为你给出了一个很好的解释。我认为如果您添加我在回答中提到的这一点会很好,以便其他人可以看到。再次感谢。【参考方案4】:
简单快速的解决方案。
myTable ID*, Field2, Filed3...
假设您的 SortOrder 仅包含 主键
SELECT TOP PageItemsCount tb01.*
FROM myTable AS tb01
LEFT JOIN (
SELECT TOP OffsetValue ID FROM myTable ORDER BY ID ASC
) AS tb02
ON tb01.ID = tb02.ID
WHERE ISNULL(tb02.ID)
ORDER BY tb01.ID ASC
-
SortOrder 基于具有重复值的其他字段,在这种情况下您必须在 SortOrder 中包含主键作为最后一个。
例如,我的表
+-------+--------+--------+
| ID | Field2 | Filed3 |
+-------+--------+--------+
| 1 | a1 | b |
| 2 | a | b2 |
| 3 | a1 | b2 |
| 4 | a1 | b |
+-------+--------+--------+
SELECT TOP 2 * From myTable ORDER BY FIELD2;
+-------+--------+--------+
| ID | Field2 | Filed3 |
+-------+--------+--------+
| 2 | a | b2 |
| 4 | a1 | b |
| 3 | a1 | b2 |
| 1 | a1 | b |
+-------+--------+--------+
SELECT TOP 2 * From myTable ORDER BY FIELD2, FIELD3;
+-------+--------+--------+
| ID | Field2 | Filed3 |
+-------+--------+--------+
| 2 | a | b2 |
| 4 | a1 | b |
| 1 | a1 | b |
+-------+--------+--------+
但如果我们将 ID 添加到排序顺序 [AS LAST IN FIELDS LIST]
SELECT TOP 2 * From myTable ORDER BY FIELD2, ID;
+-------+--------+--------+
| ID | Field2 | Filed3 |
+-------+--------+--------+
| 2 | a | b2 |
| 1 | a1 | b |
+-------+--------+--------+
最终请求
SELECT TOP PageItemsCount tb01.*
FROM myTable AS tb01
LEFT JOIN (
SELECT TOP OffsetValue ID FROM myTable ORDER BY Field2 ASC, ID
) AS tb02
ON tb01.ID = tb02.ID
WHERE ISNULL(tb02.ID)
ORDER BY tb01.Field2 ASC, tb01.ID
【讨论】:
【参考方案5】:您绝对可以使用 top 关键字获得“限制”的等价物。见:Access Database LIMIT keyword
【讨论】:
Top 关键字没有 MySQL Limit 关键字的两个参数 我确实知道TOP
关键字,并且我尽可能使用它。但是我无法模仿OFFSET
。这就是重点。
@CameronS 和@msgdie 众所周知,MySQL 的LIMIT
可以通过TOP
的组合获得,例如看Steve Jorgensen 的回答。对于@Zeki,您的回答并不完整,它看起来更像是评论,并且您提供的链接并不真正涉及有关LIMIT
的问题。请详细说明如何获得LIMIT
的模拟,我会投票给你。【参考方案6】:
不,JET SQL 没有直接等效项。作为一种解决方法,您可以添加一个WHERE
子句,在两个值之间选择一个有序/id 列。
如果可能,您还可以对现有 MySQL/其他数据库使用直通查询。
虽然 MS-Access 中的 TOP
可以限制返回的记录,但它不像 MySQL 的 LIMIT
关键字那样需要两个参数(参见 this question)。
【讨论】:
谢谢。讨厌 MS Access 的另一个原因。以上是关于MS 访问限制 X、Y的主要内容,如果未能解决你的问题,请参考以下文章