Squeel请求和Heroku,Postgres:使用GROUP BY和ORDER时出错

时间:2012-10-30 18:11:23

标签: postgresql heroku squeel

我正在使用mysql开发我的应用程序,但我使用Heroku来部署它并被迫使用PG。

我对以下声明有疑问:

<% current_user_savings = Saving.where{user_id == my{current_user}} %>      

<% @latest_savings =  Saving.where{product_id.not_in(current_user_savings.select{product_id})}.group{product_id} %>

因此它可以在我的计算机上运行,​​但在部署到heroku时,我遇到以下问题:

ActionView::Template::Error (PGError: ERROR:  column "savings.id" must appear in the GROUP      BY clause or be used in an aggregate function
LINE 1: SELECT "savings".* FROM "savings"  WHERE "savings"."product_...
SELECT "savings".* FROM "savings"  WHERE "savings"."product_id" NOT IN (SELECT "savings"."product_id" FROM "savings"  WHERE "savings"."user_id" = 1) GROUP BY "savings"."product_id"):

我真的不知道如何修复它并让它在heroku上运行。

请求的Gemfile:         来源'https://rubygems.org'

ruby '1.9.3'
gem 'rails', '3.2.7'
gem 'compass_twitter_bootstrap', '2.0.3'
gem 'bcrypt-ruby', '3.0.1'
gem 'faker', '1.0.1'
gem 'will_paginate', '3.0.3'
gem 'bootstrap-will_paginate', '0.0.6'
gem 'omniauth-facebook', '1.4.0'
gem 'railroady'
gem 'devise', '2.1.2'
gem 'devise_invitable'
gem 'simple_form'
gem "mongoid", "~> 3.0.0"
gem 'thin'
gem 'best_in_place'
gem "jquery-fileupload-rails"
gem 'paperclip'
gem "squeel"
gem 'client_side_validations'
gem 'wicked'
gem 'koala'
gem 'aws-sdk'
gem 'bson_ext'


group :development, :test do
    gem 'sqlite3'
end
group :development, :test do
    gem 'annotate', '2.5.0'
end

group :test, :development do
    gem 'rspec-rails'
end

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'compass-rails', '1.0.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'jquery-ui-rails'

group :test do
    gem 'capybara'
    gem 'factory_girl_rails'
end

group :production do
    gem 'pg', '0.12.2'
end 

4 个答案:

答案 0 :(得分:1)

我认为这些代码中的一些属于范围或至少属于您的控制器。但除此之外,你可以发布你的Gemfile吗?

在我看来,最好的做法是在开发中使用相同的数据库和ORM。你试过在本地运行PG吗?

看起来这里可能会发生一些让你很难过的事情,首先让PG在你的开发机器上本地运行并更新你的databases.yml以便重合。

其次,你也使用MongoBD吗?如果您不再使用它,可能会从包中删除它。

我稍微清理了你的Gemfile以使其更容易阅读,但我建议将宝石分组,以更好地代表宝石在项目中的角色,我喜欢记录每个宝石,以便明白是什么通常情况下,rails应用程序倾向于以巨大的Gemfile结束,这使得拾取其他人的项目变得非常困难:

source 'https://rubygems.org'
ruby '1.9.3'

gem 'rails', '3.2.7'

gem 'compass_twitter_bootstrap', '2.0.3'
gem 'bcrypt-ruby', '3.0.1'
gem 'faker', '1.0.1'
gem 'will_paginate', '3.0.3'
gem 'bootstrap-will_paginate', '0.0.6'
gem 'omniauth-facebook', '1.4.0'
gem 'railroady'
gem 'devise', '2.1.2'
gem 'devise_invitable'
gem 'simple_form'
gem 'best_in_place'
gem "jquery-fileupload-rails"
gem 'paperclip'
gem "squeel"
gem 'client_side_validations'
gem 'wicked'
gem 'koala'
gem 'aws-sdk'

gem 'pg', '0.12.2'

gem 'jquery-rails'
gem 'jquery-ui-rails'

group :development, :test do
    gem 'annotate', '2.5.0'
    gem 'rspec-rails'
end

group :test do
    gem 'capybara'
    gem 'factory_girl_rails'
end

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'compass-rails', '1.0.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

最后,请查看您的application.rb,并确保ActiveRecord可用,看起来似乎必须这样,但看一看,您可能在顶部附近的某处有require "rails/all"

答案 1 :(得分:1)

GROUP BY is a known pain point when users are migrating from MySQL to PostgreSQL

正如@rs所说,你的SQL有些问题。

如果您按主键分组

假设savings.product_id是主键,因为这是该查询唯一的正确方法,它依赖于数据库知道主键分组隐式地将所有字段分组,因为主键是唯一的。

MySQL不知道,它只是继续并选择它为每个字段看到的第一个结果。在这种情况下,这是正确的,因为您按主键进行分组,但在其他情况下很容易产生不可预测的结果。

PostgreSQL 9.0及以下版本认识到按主键分组意味着您已对所有字段进行分组,尽管SQL-99标准要求它这样做。这些版本要求您在SELECT中列出您想要GROUP BY的所有字段。这很笨拙,所以你能做的最好的事情是upgrade to PostgreSQL 9.1 or 9.2, which are no longer subject to this limitation

由于您正在使用查询生成器,处理此问题变得更加复杂。您不能只修改您的SQL。如果你无法升级PostgreSQL,你需要弄清楚如何说服你的查询生成器GROUP BY表中的所有列。

如果您按其他字段分组

如果savings.product_id不是主键,则您的查询完全错误。您必须在SELECT的{​​{1}}列表中列出所需的每个字段,以保证唯一且明确的结果,或仅引用聚合函数中的字段。

MySQL无论如何都会执行此查询,但它依赖于您知道结果将是明确的。如果某个字段有多个可能的值,它只会选择它首先获得的任何值。

在这种情况下,很难弄清楚你的查询实际应该做什么以及你期望得到什么结果。

答案 2 :(得分:1)

谢谢大家的帮助,我最终做到了这一点,并且正在本地开展PG工作!

Saving.select("DISTINCT ON (savings.product_id) * ").where{product_id.not_in(current_user_savings.select{product_id})}.group("savings.user_id, savings.updated_at, savings.id, savings.product_id, savings.price,savings.wishlist_id, savings.saved, savings.created_at")

有了这个问题让我将我的数据库从mysql切换到dev中的pg所以在heroku中没有更多的惊喜!

答案 3 :(得分:0)

您的SQL在PG中不起作用,MySQL将允许您这样做但不允许其他任何DBMS

此查询:

SELECT "savings".* FROM "savings"  
WHERE "savings"."product_id" 
NOT IN (SELECT "savings"."product_id" FROM "savings"  
         WHERE "savings"."user_id" = 1) 
GROUP BY "savings"."product_id"

应该是

SELECT "savings"."product_id", count(*) FROM "savings"  
--change this to your AGGR func
WHERE "savings"."product_id" 
NOT IN (SELECT "savings"."product_id" FROM "savings"  
         WHERE "savings"."user_id" = 1) 
GROUP BY "savings"."product_id"