2012-03-18 17 views
14

我有以下查询:Rails 3,ActiveRecord,PostgreSQL - “.uniq”命令不起作用?

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15).uniq 

,并给我的错误

PG::Error: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list 
LINE 1: ...s"."user_id" WHERE (articles.user_id != 1) ORDER BY Random() L... 

当我更新原始查询到

Article.joins(:themes => [:users]).where(["articles.user_id != ?", current_user.id]).order("Random()").limit(15)#.uniq 

所以错误消失...在MySQL .uniq的作品中,在PostgreSQL中没有。存在任何替代方案?

+0

你确定用'uniq'查询返回不同的结果吗?请为每个变体显示实际的SQL查询(使用'sql'方法)。 – taro 2012-03-18 14:01:39

+0

我确定。当我在MySQL数据库中使用这个查询时,如果没有'.uniq',它也会返回同一行,但'.uniq'总是唯一的行。在PostgreSQL中,如果我使用'.uniq',我得到了上面指定的错误,如果我不使用'.uniq',所以错误消失了,但是我也得到了来自数据库的相同行。 – user984621 2012-03-18 14:47:54

回答

30

由于错误状态for SELECT DISTINCT, ORDER BY expressions must appear in select list。 因此,您必须明确选择您要订购的子句。

下面是一个例子,它与你的情况类似,但是概括了一下。

Article.select('articles.*, RANDOM()') 
     .joins(:users) 
     .where(:column => 'whatever') 
     .order('Random()') 
     .uniq 
     .limit(15) 

所以,明确包括您ORDER BY条款(在这种情况下RANDOM())使用.select()。如上所示,为了让您的查询返回文章属性,您还必须明确地选择它们。

我希望这有助于;祝你好运

+2

为什么你必须在postgresql的第一个位置添加你所订购的select子句。如果你使用的是连接,那么sql应该足够聪明,知道要排序的内容,而不必在select子句中显式声明它(尤其是因为select子句旨在限制返回的列)。 – JohnMerlino 2013-04-03 16:57:13

+0

不包含'RANDOM()'是否完全否定'DISTINCT',因为它考虑了一组完全独特的值?因此,如果您最初没有使用过“DISTINCT”,您最终会得到重复的记录? – 2016-08-06 16:05:28

1

我假设.uniq方法在SQL上转换为DISTINCT子句。 PostgreSQL是挑剔的(比MySQL更挑剔) - 使用DISTINCT时,选择列表中的所有字段必须出现在ORDER_BY(和GROUP_BY)子句中。

这是有点不清楚你试图做什么(随机排序?)。除了发布完整的SQL发送之外,如果您可以解释您的目标,那么可能有助于找到替代方案。

+0

大概你是对的,但存在任何优雅的方式来集成在'DISTINCT' clausule上面的查询中?我目前的查询是“非常短”,我可以使用'find_by_sql'并直接设置'DISTINCT' clausule,但在这种情况下,查询要大得多。 – user984621 2012-03-19 08:33:24

0

我刚刚将我的100%工作和测试的应用程序从3.1.1升级到3.2.7,现在有了相同的PG :: Error。

我使用惨惨......

@users = User.accessible_by(current_ability).order( 'L-NAME ASC')。uniq的

卸下.uniq解决了这个问题,这是没有必要的无论如何对于这个简单的查询。

继续浏览3.1.1和3.2.7之间的变化注释,看看是什么导致了这个突破。

2

只是为了丰富具有更多示例的线程,以防在查询中嵌套关系时,可以使用以下语句尝试。

Person.find(params[:id]).cars.select('cars.*, lower(cars.name)').order("lower(cars.name) ASC") 

在给定的例子,你问都为特定人的汽车,按型号名称(奥迪,法拉利,保时捷)

我不认为这是一个更好的方式订购,但可能有助于解决这种在对象和集合中思考的情况,而不是关系数据库的方式。

谢谢!