【问题标题】:Postgres LIMIT/OFFSET strange behaviourPostgres LIMIT/OFFSET 奇怪的行为
【发布时间】:2017-06-20 05:39:12
【问题描述】:

我使用的是 PostgreSQL 9.6。我有一个这样的查询:

SELECT anon_1.id AS anon_1_id, anon_1.is_valid AS anon_1_is_valid, anon_1.first_name AS anon_1_first_name, anon_1.last_name AS anon_1_last_name,
anon_1.patronymic_name AS anon_1_patronymic_name,
anon_1.experience AS anon_1_experience, anon_1.user_id AS anon_1_user_id, anon_1.rating_points as rating_points

FROM (SELECT DISTINCT ON (doctors.id) doctors.id AS id, doctors.created_at AS created_at, doctors.updated_at AS updated_at, doctors.is_valid AS is_valid, doctors.pretty_url AS pretty_url, doctors.first_name AS first_name, doctors.last_name AS last_name, doctors.patronymic_name AS patronymic_name, doctors.phone AS phone, doctors.birthday AS birthday, doctors.avatar AS avatar, doctors.experience AS experience, doctors.science_degree AS science_degree, doctors.sex_id AS sex_id, doctors.yclients_staff_id AS yclients_staff_id, doctors.user_id AS user_id, doctor_has_specialties.rating_points AS rating_points, clinic_branch_has_doctors.price AS price, clinic_branch_has_doctors.doctor_type AS doctor_type, clinic_branch_has_doctors.is_house_call AS is_house_call, clinic_branch_has_doctors.house_call_price AS house_call_price 
FROM doctors
      JOIN doctor_has_specialties ON doctors.id = doctor_has_specialties.doctor_id 
      JOIN clinic_branch_has_doctors ON doctor_has_specialties.id = clinic_branch_has_doctors.doctor_has_specialty_id 
      JOIN clinic_branches ON clinic_branches.id = clinic_branch_has_doctors.clinic_branch_id 
      JOIN city_areas ON city_areas.id = clinic_branches.city_area_id 
      JOIN cities ON cities.id = city_areas.city_id 
WHERE doctors.is_valid = true 
      AND clinic_branch_has_doctors.is_valid = true 
      AND clinic_branches.is_valid = true 
      AND doctor_has_specialties.specialty_id = 1
      AND cities.id = 1) AS anon_1 ORDER BY anon_1.rating_points DESC 
 LIMIT 100 OFFSET 0

这里查询最重要的部分是最后一个,LIMIT 和OFFSET。 当我运行这个查询时,我的所有数据最多 100 行。一切都很好不是。这是pgAdmin的截图:

此处通知 id 为 20 的行。 现在,如果我尝试偏移 10,我会按预期从第 11 行获取我的数据,这是 id 为 22 的对象。一切都很好。 但是如果我尝试 OFFSET 10 LIMIT 10,我会得到奇怪的结果。主要是 id 20 的行也出现了,但它不应该出现。这是屏幕截图:

不知道这有什么问题。是 Postgres 错误吗?或者我做错了什么。

【问题讨论】:

  • 您使用的是ORDER BY anon_1.rating_points,那么您为什么希望anon_1_id 列与正在返回的记录有任何关联?
  • @TimBiegeleisen,是的,我知道,但是我的数据开始第 5 行的 rating_points 为 1000,只有前 5 行的 rating_points 更高。所以我希望结果与我的第一个查询一致
  • 您的示例输出缺少评级列并且也难以辨认。请编辑您的问题并向我们展示有意义的输出,然后指出您认为这是错误的原因。
  • @TimBiegeleisen,我更新了我的截图

标签: sql postgresql limit


【解决方案1】:

这里没有“错误”在起作用。您指定了以下顺序,在应用 LIMITOFFSET 时使用:

ORDER BY anon_1.rating_points DESC

但是,如果两个或多个记录与相同的rating_points 值相关联,Postgres 不保证顺序是什么。这就是为什么您会看到anon_id_120 的用户显然在四处走动。 Postgres 没有做错任何事;它尊重您通过rating_points 订购的请求,但您从未告诉它遇到领带时该怎么做。

要解决此问题,您可以向ORDER BY 添加第二个条件:

ORDER BY
    anon_1.rating_points DESC,
    anon_id_1

这将打破关于排序的关系,并且假设anon_id_1 是主键,在进行此更改后结果看起来很稳定。

【讨论】:

  • 非常感谢 :),我确信它是如此简单以至于我错过了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-30
  • 1970-01-01
相关资源
最近更新 更多