我遇到了一个关于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使用的是什么版本
答案 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 ...