0

我在 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,即没有 ActiveRecord 魔法

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

4

3 回答 3

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

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

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

您可能有多个相同的条目,created_at因此我id DESC在 ORDER BY 中添加了一个以强制 PostgreSQL 选择具有最高id. 当他们真的想得到你并且错误肯定会得到你时,偏执并没有错。

此外,您希望DESC在您的 ORDER BY 中将最高值放在顶部,ASC将最低值放在顶部。越近的时间戳越高。

一般来说,GROUP BY 和 SELECT必须匹配,因为:

当 GROUP BY 存在时,除非在聚合函数中,否则 SELECT 列表表达式引用未分组的列是无效的,因为对于未分组的列将返回多个可能的值。

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

可能有多种其他方法可以做到这一点,但这种方法可能与您将要获得的一样简单明了。

于 2011-07-22T21:41:13.810 回答
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;   
于 2011-07-22T18:18:36.357 回答
0

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

如果一切都失败了,你总是可以用一些 GROUP BY...

于 2011-07-22T18:29:49.070 回答