ActionView :: Template :: Error(PG ::错误:错误:对于SELECT DISTINCT,ORDER BY表达式必须出现在选择列表中
我正在创建一个活动网站,我正在尝试按事件的开始时间对渲染的rsvps进行排序。有很多RSVPS,所以我将它们分组,但我在过去的几天里在排序结果时遇到了很多困难而没有在PG上弹出这个错误。我已经看了一些关于这个主题的先前问题,但我仍然很丢失。我怎样才能让它发挥作用?非常感谢你!
@rsvps = Rsvp.where(:voter_id => current_user.following.collect {|f| f["id"]}, :status => 'going').where("start_time > ? AND start_time < ?", Time.now, Time.now + 1.month).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }
<%= render :partial => 'rsvps/rsvp', :collection => Rsvp.where(:event_id => @rsvps).select("DISTINCT(event_id)").order('start_time asc') %>
答案 0 :(得分:62)
我知道这是一个相当陈旧的问题,但我只是通过一个小例子来帮助我理解为什么Postgres对SELECT DISTINCT / ORDER BY列有这种看似奇怪的限制。
想象一下,您的Rsvp表中包含以下数据:
event_id | start_time
----------+------------------------
0 | Mar 17, 2013 12:00:00
1 | Jan 1, 1970 00:00:00
1 | Aug 21, 2013 16:30:00
2 | Jun 9, 2012 08:45:00
现在,您想要获取不同event_ids的列表,这些event_ids按其各自的start_times排序。但1
应该去哪里?它应该是第一个,因为一个元组从1970年1月1日开始,还是应该因为2013年8月21日而持续?
由于数据库系统无法为您做出决定,并且查询的语法不能依赖于它可能正在运行的实际数据(假设event_id
是唯一的),我们仅限于订购仅限SELECT
子句中的列。
至于实际问题 - 马修回答的另一种方法是使用像MIN
或MAX
这样的聚合函数进行排序:
SELECT event_id
FROM Rsvp
GROUP BY event_id
ORDER BY MIN(start_time)
start_time
上的显式分组和聚合允许数据库提供结果元组的明确排序。但请注意,在这种情况下,可读性肯定是一个问题;)
答案 1 :(得分:49)
ORDER BY子句只能在应用DISTINCT后应用。由于DISTINCT操作只考虑SELECT语句中的字段,因此这些字段可以在ORDER BY中使用。
逻辑上,如果您只想要一个不同的event_id值列表,它们发生的顺序应该是无关紧要的。如果订单确实很重要,那么您应该将start_time添加到SELECT列表中,以便订单有上下文。
另外,这两个SELECT子句不等效,所以要小心:
SELECT DISTINCT(event_id, start_time) FROM ...
SELECT DISTINCT event_id, start_time FROM ...
第二种是你想要的形式。第一个将返回一系列记录,数据表示为ROW构造(单个列,里面有元组)。第二个将返回正常的数据输出列。它仅在单列情况下按预期工作,其中ROW结构减少,因为它只是一列。
答案 2 :(得分:0)
因为您使用的是start_time列,所以可以使用Window Functions of PostgreSQL之一的row_number()并将其堆叠在
中启动时间的顺序,如果您希望第一个启动时间具有行值
从(SELECT event_id中选择event_id ,ROW_NUMBER()OVER(PARTITION BY event_id ORDER BY start_time)AS first_row FROM Rsvp),其中first_row = 1
开始时间的倒序,如果您期望最后一个开始时间的行值
从(SELECT event_id中选择event_id ,ROW_NUMBER()OVER(PARTITION BY event_id ORDER BY start_time desc)AS last_row FROM Rsvp),其中last_row = 1
您还可以根据需要使用其他Window Function。
答案 3 :(得分:0)
我能够通过在我的选择中添加一列然后在该列上使用 ORDER BY
来解决此错误。我有 SELECT DISTINCT concat(dl.FirstName, concat(' ', dl.LastName)) as displayName, ...
并且我想 ORDER BY
姓氏(就像一个人所做的那样)。我尝试了所有我能想到的在 ORDER BY
中添加 SELECT
的排列,但有效的只是添加 , dl.LastName as lastName
然后在查询的末尾添加 ORDER BY lastName ASC
,如一个更典型的查询。
我最后增加了一个列,但在我的应用程序中很容易忽略它。