【问题标题】:SQL SELECT ... WHERE IN with separate LIMIT,OFFSET clauseSQL SELECT ... WHERE IN 带有单独的 LIMIT,OFFSET 子句
【发布时间】:2013-08-19 12:14:49
【问题描述】:

我有简单的 SQL 查询:

SELECT * FROM t1 
WHERE status = 1 AND user_id = ? AND some_field NOT IN (?, ?, ..., ?)
ORDER BY createdAt DESC, rating DESC
LIMIT 10 OFFSET 0;

但我想在我的 PHP 代码中对没有循环的用户集合执行类似的查询。看起来我需要在 user_id = 中使用 IN 子句?条件 (user_id IN (?,...?)) 并为 user_id IN 子句中的每个 id 单独的 LIMIT,OFFSET 子句。我知道这是不可能的,但可能存在任何变通方法而不降低我的查询性能?

我使用 PostgreSQL 9.0.3,并且我认为也可以使用存储过程来解决这个问题。

【问题讨论】:

  • 第一:9.0.3?!?您落后于许多重要的补丁版本,包括关键的安全更新。现在升级。见postgresql.org/support/versioningpostgresql.org/support/security/faq/2013-04-04
  • 至于问题本身,我发现很难弄清楚到底是什么问题,你要解决什么问题。
  • 我完全没有得到问题,你是想按 10 行获取数据还是什么?
  • 现在我有 N 个单独的查询,其中 user_id = YYY 子句在每个这样的查询上都有相同的 LIMIT,OFFSET 条件。检索到的数据在 PHP 端聚合到单个集合中。但是我想直接在 DB 端形成结果集合,而在 PHP 端没有任何循环,并将其作为单个查询结果或存储过程调用结果省略。

标签: sql postgresql where-in


【解决方案1】:
select *
from (
    select *,
        row_number() over(
            partition by user_id
            order by createdat desc, rating desc
        ) as rn
    from t1 
    where
        status = 1 and some_field not in (?, ?, ..., ?)
        and user_id in (1,2,3)
) s
where rn <= 10
order by user_id, rn

窗口函数:

http://www.postgresql.org/docs/current/static/functions-window.html

http://www.postgresql.org/docs/current/static/sql-expressions.html#SYNTAX-WINDOW-FUNCTIONS

http://www.postgresql.org/docs/current/static/tutorial-window.html

【讨论】:

  • 看起来很神奇!尝试使用它。那么这个查询的性能呢?
  • @Ostrovski 窗口函数很昂贵。要了解有关 postgresql 查询成本的更多信息,请查找 explain
  • 哦,太慢了。即使我在单独的查询中这样做,我的循环选择也快了大约 10 倍。
  • @Ostrovski 如果您限制 user_id,成本会大大降低。检查更新的答案。
  • 更快,但也只有几百毫秒。
猜你喜欢
  • 2016-03-11
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 2012-08-12
相关资源
最近更新 更多