【问题标题】:DISTINCT ON query w/ ORDER BY max value of a columnDISTINCT ON 查询 w/ ORDER BY 列的最大值
【发布时间】:2015-04-01 16:29:19
【问题描述】:

我的任务是尽快将 Rails 应用程序从 MySQL 转换为 Postgres,但遇到了一个小问题。
活动记录查询:

current_user.profile_visits.limit(6).order("created_at DESC").where("created_at > ? AND visitor_id <> ?", 2.months.ago, current_user.id).distinct

生成 SQL:

SELECT  visitor_id, MAX(created_at) as created_at, distinct on (visitor_id) *
FROM "profile_visits"
WHERE "profile_visits"."social_user_id" = 21
AND (created_at > '2015-02-01 17:17:01.826897' AND visitor_id <> 21)
ORDER BY created_at DESC, id DESC
LIMIT 6

我在使用 MySQL 时非常自信,但我对 Postgres 说实话还是很陌生。我认为这个查询失败的原因有很多。

  1. 我认为首先需要区分。
  2. 不知道怎么按max函数的结果排序
  3. 我什至可以像这样使用 max 函数吗?

此查询的高级目标是返回用户最近的 6 次个人资料视图。任何有关如何修复此 ActiveRecord 查询(或其生成的 SQL)的指针将不胜感激。

【问题讨论】:

  • 有问题的查询不适用于 MySQL。 distinct on 是一个 Postgres 构造,所以我认为整个事情都是 Postgres 兼容的。但是,max() 的使用非常可疑。
  • 与往常一样,您的 Postgres 版本和表定义应该在问题中。此外,查询应该做什么的描述可能不完整。

标签: mysql sql ruby-on-rails postgresql activerecord


【解决方案1】:

此查询的高级目标是返回 6 个最近的 用户的个人资料视图

那很简单。你不需要max() 也不需要DISTINCT

SELECT *
FROM   profile_visits
WHERE  social_user_id = 21
AND    created_at > (now() - interval '2 months')
AND    visitor_id <> 21  -- ??
ORDER  BY created_at DESC NULLS LAST, id DESC NULLS LAST
LIMIT  6;

我怀疑你的问题不完整。如果您想要:
最近访问该页面的 6 位访问者
那么你需要一个子查询。您无法在一个查询级别获得这种排序顺序,无论是使用DISTINCT ON,还是使用窗口函数:

SELECT *
FROM  (
   SELECT DISTINCT ON (visitor_id) *
   FROM   profile_visits
   WHERE  social_user_id = 21
   AND    created_at > (now() - interval '2 months')
   AND    visitor_id <> 21  -- ??
   ORDER  BY visitor_id, created_at DESC NULLS LAST, id DESC NULLS LAST
   ) sub
ORDER  BY created_at DESC NULLS LAST, id DESC NULLS LAST
LIMIT  6;

子查询sub 获取每个用户的最新访问(但不超过两个月且不针对某个访问者21ORDER BY 必须与DISTINCT ON 具有相同的前导列。

然后,您需要外部查询来获取 6 个最新访问者。
考虑事件的顺序:

为什么是NULLS LAST?可以肯定的是,您没有提供表定义。

【讨论】:

    猜你喜欢
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 2012-04-05
    • 2016-11-13
    • 1970-01-01
    • 2013-01-25
    相关资源
    最近更新 更多