【发布时间】:2011-12-24 21:46:11
【问题描述】:
是否可以模拟以下 MySQL 查询:
SELECT * FROM `tbl` ORDER BY `date` DESC LIMIT X, 10
(X是参数)
在 MS Access 中?
【问题讨论】:
标签: ms-access
是否可以模拟以下 MySQL 查询:
SELECT * FROM `tbl` ORDER BY `date` DESC LIMIT X, 10
(X是参数)
在 MS Access 中?
【问题讨论】:
标签: ms-access
虽然 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。
【讨论】:
另一种方式 - 假设您希望在一个名为 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
【讨论】:
更好的查询是:
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。用户列表按注册日期排序(降序)。
【讨论】:
X 评论怎么样 - 我不太明白你在这里。这很好,因为如果我们以我发布的示例为例,最后一页(page = 2)的查询将是SELECT TOP 2 以上SELECT TOP 20,实际上只会给您预期的两个结果。它永远不会重复前几页中的行,因为它是由total_rows - offset 计算的。所以对我来说一切都很好。
简单快速的解决方案。
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
例如,我的表
+-------+--------+--------+
| 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
【讨论】:
您绝对可以使用 top 关键字获得“限制”的等价物。见:
Access Database LIMIT keyword
【讨论】:
TOP 关键字,并且我尽可能使用它。但是我无法模仿OFFSET。这就是重点。
LIMIT 可以通过TOP 的组合获得,例如看Steve Jorgensen 的回答。对于@Zeki,您的回答并不完整,它看起来更像是评论,并且您提供的链接并不真正涉及有关LIMIT 的问题。请详细说明如何获得LIMIT 的模拟,我会投票给你。
不,JET SQL 没有直接等效项。作为一种解决方法,您可以添加一个WHERE 子句,在两个值之间选择一个有序/id 列。
如果可能,您还可以对现有 MySQL/其他数据库使用直通查询。
虽然 MS-Access 中的 TOP 可以限制返回的记录,但它不像 MySQL 的 LIMIT 关键字那样需要两个参数(参见 this question)。
【讨论】: