【问题标题】:PostgreSQL Error for Select Distinct in Rails在 Rails 中选择不同的 PostgreSQL 错误
【发布时间】:2012-10-24 05:58:47
【问题描述】:

在 Mysql 上它可以正常工作。

PG::Error: ERROR: 对于 SELECT DISTINCT,ORDER BY 表达式必须 出现在选择列表第 1 行:) ORDER BY programs.rating DESC,program_sc... ^ :

查询:

SELECT DISTINCT "programs".* FROM "programs" INNER JOIN "program_schedules" ON "program_schedules"."program_id" = "programs"."id" WHERE (programs.rating >= 5 AND program_schedules.start >= '2012-11-03 23:14:43.457659') AND (ptype = '电影') ORDER BY programs.rating DESC, program_schedules.start DESC

Rails 代码:

@数据 = Program.joins(:program_schedules).where('programs.rating >= ? AND program_schedules.start >= ?',5, Time.now).order('programs.rating DESC, program_schedules.start DESC').uniq

我试过了

Program.select("程序.*, program_schedules.*).joins(:program_schedules).where(...

但是,这样,当我要阅读时

@data.program_schedules

我得到一个 nil 值(当我知道没有 nil 值时)

PostgreSQL 9.2 (Heroku)、Ruby 1.9.2

关于我的数据库的一些信息:

class Program < ActiveRecord::Base
   has_many :program_schedules
end


class ProgramSchedule < ActiveRecord::Base
  belongs_to :program
end

Schema.db

 create_table "program_schedules", :force => true do |t|
        t.integer  "program_id"
        t.datetime "start"
  end

  create_table "programs", :force => true do |t|
    t.string  "title",
    t.string  "ptype"
  end

编辑: 我不需要订购“programs_schedules”,因为我需要数组中与该程序相关的所有programs_schedules。

【问题讨论】:

  • 这是一个足够复杂的查询,我只需要使用find_by_sql
  • As always:PostgreSQL 的版本?对于程序员来说应该不言而喻.. 表定义也绝不是一个坏主意。会澄清ptype 的来源。
  • 好的,我已经更新了我的问题帖子

标签: ruby-on-rails ruby-on-rails-3 postgresql rails-postgresql


【解决方案1】:

您的查询有两种歧义:

ptype 不是表限定的,您没有透露表定义。所以查询是模棱两可的。

更重要的是,您想要:

ORDER BY programs.rating DESC, program_schedules.start DESC

然而,与此同时,您指示 PostgreSQL 为您提供来自 programsDISTINCT 行。如果program_schedules 中有多个匹配的行,Postgres 怎么知道为ORDER BY 子句选择哪一个?首先?最后的?最早、最新、最环保?它只是未定义。

通常,ORDER BY 子句不能与 DISTINCT 子句不一致,这就是错误消息告诉您的内容。

基于一些假设,填写缺失的信息,您的查询可能如下所示:

SELECT p.*
FROM   programs p
JOIN   program_schedules ps ON ps.program_id = p.id
WHERE  p.rating >= 5
AND    ps.start >= '2012-11-03 23:14:43.457659'
AND    p. ptype = 'movie'   -- assuming ptype is from programs  (?)
GROUP  BY p.id              -- assuming it's the primary key
ORDER  BY p.rating DESC, min(ps.start) DESC;  -- assuming smallest start

还假设您有 PostgreSQL 9.0 或更高版本,这是工作所必需的。 (主键覆盖GROUP BY中的整个表。)

至于:

在 Mysql 上它可以正常工作。

不,它没有。它“有效”,但以神秘的方式而不是“正确”。 MySQL 允许各种奇怪的错误,并竭尽全力(和 SQL 标准)以避免抛出异常——这是处理错误的一种非常不幸的方式。它经常回来困扰你。 Demo on Youtube.

问题更新

我需要数组中与该程序相关的所有programs_schedules。

您可能需要添加:

SELECT p.*, array_agg(ps.start ORDER BY ps.start)

【讨论】:

  • +1!特别感谢视频链接。下次我发现自己说同样的话时,我会保留它。
  • 好的,谢谢。我已经更新了我的问题帖子。现在我要检查您的查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 2013-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-24
相关资源
最近更新 更多