【问题标题】:Keyset pagination with multiple columns具有多列的键集分页
【发布时间】:2021-08-27 06:20:29
【问题描述】:

我正在尝试使用多列进行键集分页,但除了第一个之外,我无法让它在任何页面上工作。键集列中的一列也可以为空 (col1) 并使用 nulls last 排序。

select colId, col1, col2 from tablename
where (case when parameter_col1 is null then true else col1 < parameter_col1)
and (case when parameter_col2 is null then true else col2 < parameter_col2)
and (case when parameter_colId is null then true else colId < parameter_colId)
order by col1 desc nulls last, col2 desc, colId desc
limit 10;

我在每个where 中使用这些case 语句,以便在结果的第一页上,当null 为所有3 个parameter_ 值传递时,所有内容都会返回。所以它在结果的第一页上运行良好。

但在第二页上,无论parameter_col1 是否为空,它都不会返回正确的结果。使用多列(其中一些可以为空)进行分页的正确方法是什么?

将其分成 2 个单独的查询是否有帮助,一个用于第一页,另一个用于所有后续查询?如果可能的话,我更愿意将它组合到一个查询中以便于维护,但如果不是,我可以将两个查询放入 sqlplpgsql 类型的函数中,这样它们至少在同一个地方,并使用if 选择使用哪个。

【问题讨论】:

  • WHERE 子句中使用AND/OR 结构而不是case 表达式 通常会更好。
  • 你能展示一下它应该是什么样子吗?
  • (parameter_col1 is null OR col1 &lt; parameter_col1)
  • 我可以用 and/or 重写这种类型的 where 子句吗? where col = case when param is null then col else param

标签: sql postgresql pagination


【解决方案1】:

选择一个小于所有可能的col1 值的值并将其与coalesce 一起使用。例如,如果col1timestamp 类型,您可以使用'-infinity',查询看起来像

SELECT colId, col1, col2 from tablename
WHERE ROW(coalesce(col1, '-infinity'), col2, colId)
    < ROW(coalesce(parameter_col1, 'infinity'), parameter_col2, parameter_colId)
ORDER BY coalesce(col1, '-infinity') DESC, col2 DESC, colid DESC
LIMIT 10;

使用ORDER BY 表达式上的索引可能会很快。

【讨论】:

  • 在 postgres 分页示例中,我总是看到一个 WHERE 和一个 &lt;&gt;。如果您的ORDER BY 全部为ASC 或全部DESC 列,是否有必要这样做,或者ROW 语法只是一种更简单的编写方式?因为如果某些列是ASC,而有些列是DESC,那么您不能使用ROW,而必须将WHERE 与多个AND 一起使用?
  • 如果不这样比较,就不能使用(多列)索引。
  • 结果的第二页与第一页的结果完全相同。当parameter_col1null 并且parameter_col2 不是null(结果的第二页)时,它给出的结果与两者都是null(结果的第一页)时相同。我在问题中给出了一个简化的示例,但实际上col2 来自inner join 表。这可能使索引不可能,但你的答案应该仍然有效。你知道为什么第二页的结果是一样的吗?
  • @user779159 您无法准确运行 Laurenz 的查询,因为它有语法错误。请编辑我们的问题以显示您运行的确切查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-29
  • 2017-07-15
  • 2014-06-05
  • 1970-01-01
  • 2016-10-27
  • 1970-01-01
相关资源
最近更新 更多