ruby-on-rails - PG::InvalidColumnReference: 错误:对于 SELECT DISTINCT,ORDER BY 表达式必须出现在选择列表中

标签 ruby-on-rails postgresql activerecord arel

我有一长串关联、连接、排序等,最终是从我的一个 Rails 模型中进行选择。在一天结束时,我需要结果是唯一的和排序的。我不关心 SELECT 语句中使用了哪些列,ORDER BY 中出现了什么,等等(这些都根据用户选择的过滤选项而改变),我只关心顶级模型/表查询是唯一的(基于 id)。

对于背景,widgets 是主表,我们正在加入 widget_steps,这是在 Rails 3 中(公司正在尝试尽快升级,但这就是他们此刻坚持)

这是正在生成的查询和错误:

PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ...completed_at" IS NULL)) ORDER BY sequential DESC, widget_s...
                                                             ^
: SELECT  DISTINCT "widgets".* FROM "widgets" INNER JOIN "widget_steps" ON "widget_steps"."widget_id" = "widgets"."id" INNER JOIN "widget_steps" "active_steps_widgets" ON "active_steps_widgets"."id" = "widgets"."active_widget_step_id" WHERE "widgets"."account_id" = 1 AND "widgets"."completed_at" IS NULL AND (("widgets"."sequential" = 't' AND "widget_steps"."assigned_to" = 5 AND "widget_steps"."id" = "widgets"."active_widget_step_id" AND "widget_steps"."completed_at" IS NULL) OR ("widgets"."sequential" = 'f' AND "widget_steps"."assigned_to" = 5 AND "widget_steps"."completed_at" IS NULL)) ORDER BY sequential DESC, widget_steps.name ASC LIMIT 10 OFFSET 0
Completed 500 Internal Server Error in 52.3ms

ActiveRecord::StatementInvalid - PG::InvalidColumnReference: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ...completed_at" IS NULL)) ORDER BY sequential DESC, widget_s...
                                                             ^
: SELECT  DISTINCT "widgets".* FROM "widgets" INNER JOIN "widget_steps" ON "widget_steps"."widget_id" = "widgets"."id" INNER JOIN "widget_steps" "active_steps_widgets" ON "active_steps_widgets"."id" = "widgets"."active_widget_step_id" WHERE "widgets"."account_id" = 1 AND "widgets"."completed_at" IS NULL AND (("widgets"."sequential" = 't' AND "widget_steps"."assigned_to" = 5 AND "widget_steps"."id" = "widgets"."active_widget_step_id" AND "widget_steps"."completed_at" IS NULL) OR ("widgets"."sequential" = 'f' AND "widget_steps"."assigned_to" = 5 AND "widget_steps"."completed_at" IS NULL)) ORDER BY sequential DESC, widget_steps.name ASC LIMIT 10 OFFSET 0:

为什么会这样? postgres 认为什么如此模棱两可?为什么像这样的查询在 MySQL 中总是可以正常工作,但会使 postgres 窒息。

我试过:

  1. 在链的末尾指定 .select([everything mentioned in order by]).uniq
  2. 在链的末尾指定 .uniq 而不进行自定义选择
  3. 编写一些自定义 AREL 以尝试将所有这些嵌入到子查询中,然后在此之外执行 .uniq 或 .order(无法使其正常工作)
  4. 在 postgres 之外执行 .uniq(这会因为分页而中断......由于重复项被删除,您最终可能会得到一些只有 1 或 2 个项目的页面)

最佳答案

您需要将 widget_steps.name 添加到所选列的列表中:

SELECT DISTINCT "widgets".*,
                "widget_steps.name"
FROM "widgets"
INNER JOIN "widget_steps" ON "widget_steps"."widget_id" = "widgets"."id"
INNER JOIN "widget_steps" "active_steps_widgets" ON "active_steps_widgets"."id" = "widgets"."active_widget_step_id"
WHERE "widgets"."account_id" = 1
  AND "widgets"."completed_at" IS NULL
  AND (("widgets"."sequential" = 't'
        AND "widget_steps"."assigned_to" = 5
        AND "widget_steps"."id" = "widgets"."active_widget_step_id"
        AND "widget_steps"."completed_at" IS NULL)
       OR ("widgets"."sequential" = 'f'
           AND "widget_steps"."assigned_to" = 5
           AND "widget_steps"."completed_at" IS NULL))
ORDER BY sequential DESC,
         widget_steps.name ASC
LIMIT 10
OFFSET 0

这不会改变您的查询逻辑并且会正常工作。

在 Rails 中,您可以使用 select 方法来设置选定列的列表:

Widget.select('"widgets".*, "widget_steps.name"')

希望这会有所帮助。

关于ruby-on-rails - PG::InvalidColumnReference: 错误:对于 SELECT DISTINCT,ORDER BY 表达式必须出现在选择列表中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42846286/

相关文章:

返回聚合和非聚合结果的 SQL 查询

ruby-on-rails - Rails ActiveRecord 协会

ruby-on-rails - 重启后自动启动rails server

postgresql - 更新插入更改行键(串行)?

javascript - 具有 'remote: true' 的表单即使使用重定向也会返回 200 响应

postgresql - Postgres pl/pgsql 错误 : column "column_name" does not exist

ruby-on-rails - Ruby on Rails 的 varchar 迁移问题

ruby-on-rails - ActiveRecord:方法名称作为符号传递时,不调用after_initialize

ruby-on-rails - 使用 Devise after_sign_in_path_for 重定向循环

ruby-on-rails - Rails Google Client API - 无法将刷新 token 交换为访问 token