简体   繁体   English

与ORDER BY列的最大值进行查询时区别

[英]DISTINCT ON query w/ ORDER BY max value of a column

I've been tasked with converting a Rails app from MySQL to Postgres asap and ran into a small issue. 我的任务是尽快将Rails应用程序从MySQL转换为Postgres,然后遇到一个小问题。
The active record query: 活动记录查询:

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

Produces the SQL: 产生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

I'm pretty confident when working with MySQL but I'm honestly new to Postgres. 我在使用MySQL时非常有信心,但是我真的是Postgres的新手。 I think this query is failing for multiple reasons. 我认为此查询失败有多种原因。

  1. I believe the distinct on needs to be first. 我认为,与众不同需要首先。
  2. I don't know how to order by the results of max function 我不知道如何按max函数的结果排序
  3. Can I even use the max function like this? 我什至可以使用max函数吗?

The high level goal of this query is to return the 6 most recent profile views of a user. 此查询的高级目标是返回用户的6个最近的个人资料视图。 Any pointers on how to fix this ActiveRecord query (or it's resulting SQL) would be greatly appreciated. 任何有关如何解决此ActiveRecord查询(或由此产生的SQL)的指针将不胜感激。

The high level goal of this query is to return the 6 most recent profile views of a user. 此查询的高级目标是返回用户的6个最近的个人资料视图

That would be simple. 那很简单。 You don't need max() nor DISTINCT for this: 您不需要为此的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;

I suspect your question is incomplete. 我怀疑您的问题不完整。 If you want: 如果你想:
the 6 latest visitors with their latest visit to the page 最近访问该页面的6位最新访问者
then you need a subquery. 那么您需要一个子查询。 You cannot get this sort order in one query level, neither with DISTINCT ON , nor with window functions: 您不能通过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;

The subquery sub gets the latest visit per user (but not older than two months and not for a certain visitor 21 . ORDER BY must have the same leading columns as DISTINCT ON . 子查询sub获得每个用户的最新访问次数(但不超过两个月,并且不针对特定访问者21 ORDER BY必须具有与DISTINCT ON相同的前导列。

You need the outer query to get the 6 latest visitors then. 您需要外部查询才能获取最近的6位访问者。
Consider the sequence of events: 考虑事件的顺序:

Why NULLS LAST ? 为什么NULLS LAST To be sure, you did not provide the table definition. 当然,您没有提供表定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM