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 NameIdPerson 表中从偏移量 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 个,然后从表中选择匹配的行,再次按正序排序。这应该是相当有效的,假设 IdPRIMARY KEY,并且 Name 上有一个索引。可能需要针对 NameId(而不是仅针对 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 = 12Y = 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的主要内容,如果未能解决你的问题,请参考以下文章

限制用户对 MS 访问中的表和查询的访问

MS 访问限制语法

限制少数用户访问数据库。 (MS 访问 2007)

MS 访问 年龄限制在 18 岁或以上

如何限制 JSON 访问?

公网ip被X网站限制访问,现有啥手段可以继续访问X网站?