PostgreSQL DISTINCT问题:在本地工作但不在服务器上工作

时间:2011-07-22 18:14:48

标签: postgresql heroku rails-postgresql

我遇到了一个关于PostgreSQL查询的棘手问题。这适用于我的本地开发环境:

SELECT distinct (user_id) user_id, created_at, is_goodday 
FROM table 
WHERE ((created_at >= '2011-07-01 00:00:00') AND user_id = 95 
AND (created_at < '2011-08-01 00:00:00')) 
ORDER BY user_id, created_at ASC;

...但在我的QA服务器上(在Heroku上)出现以下错误:

PGError: ERROR:  syntax error at or near "user_id"
LINE 1: SELECT distinct (user_id) user_id, created_at,
                                  ^ 

为什么会这样?

其他可能相关的信息:

我尝试过单引号和双引号字段名称

这是一个Rails 3应用程序,但我正在使用这个SQL raw,即没有ActiveRecord魔法

我的本​​地版Postgres在Mac上是9.0.4,但我不知道Heroku使用的是什么版本

3 个答案:

答案 0 :(得分:1)

根据您的评论,该查询的标准PostgreSQL版本将是:

SELECT user_id, created_at, is_goodday
FROM table
WHERE created_at >= '2011-07-01 00:00:00'
  AND created_at <  '2011-08-01 00:00:00'
  AND user_id     = 95
ORDER BY created_at DESC, id DESC
LIMIT 1

您在ORDER BY中不需要user_id,因为您有user_id = 95,您希望ORDER BY中的created_at DESC将最新的created_at放在最顶层;然后你LIMIT 1切掉结果集中的第一行。 GROUP BY可用于强制执行唯一性,或者如果您需要为聚合函数分组,但您不需要其中任何一个,因为您可以通过ORDER BY和LIMIT获得唯一性,并且您可以隐藏聚合内部的聚合ORDER BY(即你不需要MAX,因为ORDER BY会为你做这件事)。

由于您的WHERE中有user_id = 95,因此您在SELECT中不需要user_id,但如果在Ruby-land中使您更容易,则可以将其保留。

您可能有多个具有相同created_at的条目,因此我在ORDER BY中添加了id DESC以强制PostgreSQL选择具有最高id的条目。当他们真的想要得到你的时候,有偏执狂并没有什么不妥,而且肯定会出错来吸引你。

此外,您希望ORDER BY中的DESC获得最高值,ASC将最低值放在顶部。最新的时间戳将是更高的时间戳。

一般情况下,GROUP BY and SELECT必须匹配,因为:

  

当GROUP BY存在时,SELECT列表表达式无法引用除聚合函数之外的未组合列,因为对于未组合列,将返回多个可能的值。

但这并不重要因为你根本不需要GROUP BY。我链接到8.3版本的文档以匹配您正在使用的PostgreSQL版本。

可能还有其他各种方法可以做到这一点,但这个方法可能就像你要获得的那样直截了当。

答案 1 :(得分:0)

在user_id中添加引用,例如user_id = '95'。您的查询应该是

SELECT distinct (user_id) as uid, created_at, is_goodday  FROM table  WHERE 
((created_at >= '2011-07-01 00:00:00') AND user_id = '95'  AND (created_at < '2011-08-01 00:00:00'))  ORDER BY user_id, created_at ASC;   

答案 2 :(得分:0)

你正在使用DISTINCT ON(不写ON)。也许你应该写ON。也许你的postgres服务器可以追溯到功能实现之前(现在已经很久了)。

如果所有其他方法都失败了,您可以随时使用某些GROUP BY ...