ste*_*com 5 sql arel ruby-on-rails-3
我拼命想弄清楚Arel,主要是因为我讨厌处理SQL; 我做得很好,但我撞墙了.
我一直在Rails 3.0.0中工作,我正在尝试使用一些数学进行复杂的查询.真实情况相当复杂,但我简化了一下.在我的例子中,我有一个带有特定字符串字段的表,我想要计算所有记录,以及该字段的两个可能值中的每一个的计数,按外部id分组.
在Rails 3.0.0下,我可以这样做(控制台命令):
t = Arel::Table.new(:some_thingies)
e = t .project(t[:foreign_id], t[:foreign_id].count.as('all_count')) .group(t[:foreign_id])
c = t.where(t[:some_field].eq('type1')).project(t[:foreign_id], t[:foreign_id].count.as('type1_count')).group(t[:foreign_id])
x = e
x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
Run Code Online (Sandbox Code Playgroud)
在这一点上,我可以做x.to_sql和...好吧,我不完全确定它是正确的,但结果看起来是正确的,除了两次foreign_id列.
SELECT
`some_thingies_external`.`foreign_id`,
`some_thingies_external`.`all_count`,
`some_thingies_external_2`.`foreign_id`,
`some_thingies_external_2`.`type1_count`
FROM
(SELECT
`some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1+count`
FROM `some_thingies`
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external`
INNER JOIN
(SELECT `some_thingies`.`foreign_id`, COUNT(`some_thingies`.`foreign_id`)
AS `type1_count`
FROM `some_thingies`
WHERE `some_thingies`.`type` = 'type1'
GROUP BY `some_thingies`.`foreign_id`) `some_thingies_external_2`
ON `some_thingies_external`.`foreign_id` = `some_thingies_external_2`.`foreign_id`
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.但是,当我尝试加入第二组这样的计数时:
i = t.where(t[:some_field].eq('type2')).project(t[:foreign_id], t[:foreign_id].count.as('type2_count')).group(t[:foreign_id])
x = x.join(i).on(e[:foreign_id].eq(i[:foreign_id]))
Run Code Online (Sandbox Code Playgroud)
它只是挂断了,让我觉得我遇到了这个bug
(顺便说一句,我有更多的计数要加入,理想情况下'some_thingies'应该是一个arel对象,代表更多过滤我们正在计算的东西......但我离题了......)
所以,我决定尝试最新的边缘Arel和Rails,并相应地提升我的宝石:
gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'rack', :git => 'git://github.com/rack/rack.git'
gem 'arel', :git => 'http://github.com/brynary/arel.git'
Run Code Online (Sandbox Code Playgroud)
现在,当我尝试做第一次加入时,它失败了:
ruby-1.9.2-preview3 > x = x.join(c).on(e[:foreign_id].eq(c[:foreign_id]))
NoMethodError: undefined method `[]' for #<Arel::SelectManager:0x00000104311e38>
from (irb):12
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:44:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands/console.rb:8:in `start'
from /Users/stephan/.rvm/gems/ruby-1.9.2-preview3/bundler/gems/rails-c42ea2172eb9/railties/lib/rails/commands.rb:33:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Run Code Online (Sandbox Code Playgroud)
这似乎不是Arel中的一个错误 - 如果有的话,它似乎更像是它以前工作的事实是bug.我想我只是不知道Arel :: SelectManager是什么以及如何处理它.看起来我做得很好,但我真的不知道发生了什么.
我是否需要以某种方式根据我得到的SelectManager创建一个新表?或者我在配置中做错了什么导致[]语法失败?或者我完全不理解Arel的作用?我仍然不太了解我应该用Arel :: Rows做什么,但我想我会得到那个; 我怀疑我可以通过项目()来摆脱结果中的额外外键...
但我还是很迷茫.Haaaaalp!
ps用"弱点"或"邮件人"做'铁路'押韵?
我要回答我自己的问题,因为似乎没有人感兴趣,现在我知道我做错了什么,我可以看到如果我理解 SQL,这将是显而易见的。
我使用 Arel 的方式的问题 1 是你只能加入一张新制作的桌子。那不是重点。
真正的问题是我正在尝试计算两个不同的东西。我真的应该按外部 ID 和“some_field”进行分组。我只是不知道你能做到这一点,而且结果有点奇怪。如果我不关心 some_field 的所有可能值,这可能会很烦人,但我确实关心它们,并且我可以轻松地将它们相加以获得总数,并且现在很容易将它们过滤掉。
t = Arel::Table.new(:some_thingies)
e = t.group(:foreign_id, :some_field).project(t[:id], t[:foreign_id], t[:some_field])
Run Code Online (Sandbox Code Playgroud)
一旦我弄清楚了这一点,我就知道如何使用普通的 ActiveRecord 而无需 ARel 来做到这一点:
SomeThing.group('foreign_id, some_field').select('id, foreign_id, some_field, count(1)')
Run Code Online (Sandbox Code Playgroud)
噢!寓意:SQL 只知道行。时期。