当我有这个查询时:
SELECT DISTINCT "spree_products".id FROM "spree_products"
INNER JOIN "spree_variants"
ON "spree_variants"."product_id" = "spree_products"."id"
AND "spree_variants"."is_master" = 't'
INNER JOIN "spree_prices"
ON "spree_prices"."variant_id" = "spree_variants"."id"
INNER JOIN "spree_products_taxons"
ON "spree_products_taxons"."product_id" = "spree_products"."id"
INNER JOIN "spree_taxons"
ON "spree_taxons"."id" = "spree_products_taxons"."taxon_id"
WHERE "spree_taxons"."id" IN (13)
AND "spree_prices"."currency" = 'USD'
AND ("spree_products".deleted_at IS NULL
or "spree_products".deleted_at >= '2013-08-30 06:23:45.881488')
AND ("spree_products".available_on <= '2013-08-30 06:23:45.881974')
AND (spree_prices.amount IS NOT NULL) LIMIT 12 OFFSET 36
Run Code Online (Sandbox Code Playgroud)
我得到一些以不同偏移量返回的记录。例如,我ID=53
在OFFSET 24
和中都看到了一条记录OFFSET 36
。
如果我ORDER BY spree_products.id
在此语句中添加一个子句,它会使顺序确定,并且我永远不会看到以不同偏移量返回的相同记录。
这是因为 SQL 标准不要求 PostgreSQL 在没有ORDER BY
子句的情况下以任何特定顺序返回行。它可以返回它们,但是感觉如何。参见手册SELECT
。特别是:
如果未给出 ORDER BY,则以系统发现最快生成的任何顺序返回行。
和
使用 LIMIT 时,最好使用 ORDER BY 子句将结果行限制为唯一顺序。否则,您将获得查询行的不可预测的子集——您可能会要求从第十行到第二十行,但从第十行到第二十行的顺序是什么?除非您指定 ORDER BY,否则您不知道什么顺序。
在几乎所有情况下,这都会造成LIMIT
和/或OFFSET
没有ORDER BY
不安全。如果您在内部查询中强制排序,这是允许的,这是一种性能技巧,但这很少是一个好主意。
您必须添加一个ORDER BY
子句以使您的语句具有确定性。
在这种情况下,在DISTINCT
那里它可能会进行哈希聚合 - 从执行到执行,它往往会以不一致的顺序返回结果。即使您正在执行通常按顺序返回结果的索引扫描,您也不能假设它会,除非您告诉 PostgreSQL 您需要按特定顺序排列的行。
这与询问如何以表格的“自然”顺序选择行的人密切相关;表和结果集不具有自然顺序。它们是集合而不是列表。如果您需要排序,则必须在逐个操作的基础上指定一个排序。
归档时间: |
|
查看次数: |
4092 次 |
最近记录: |