在我的Rails应用程序中将条件MySQL查询语法转换为Postgres

时间:2015-04-15 12:32:29

标签: mysql sql ruby-on-rails postgresql activerecord

我一直在尝试在我的Rails应用程序中转换mySQL查询以使用Postgres语法,并且一直在倾注Postgres文档,特别是查看条件之间的差异。查询是:

Story.select('*', 'IF (views.id is null, 0, 1) as viewed')
  .join('left join views on(
       views.story_id = stories.id and views.user_id = ?
     )', user.id)
  .group(:id)
  .order(viewed: :asc)
  .order(id: :asc)

或作为纯查询:

select stories.*,
  IF (views.id is null, 0, 1) as viewed
from stories
left join views
  on(views.story_id = stories.id and views.user_id = 1)
where 1
group by stories.id
order by viewed, stories.id

似乎postgres使用'case'而不是IF,所以我厌倦了这样的事情:

Story.select('*', '(case when viewid is null then 0, 1 end) as viewed')
  .join('left join views on(
       views.story_id = stories.id and view.user_id = ?
     )', user.id)
  .group(:id)
  .order(viewed: :asc)
  .order(id: :asc)

但是我得到了

错误的参数数量(2为0..1)

错误...

我尝试了几种变化,但没有运气。我打算在不久的将来更多地学习SQL,但同时我觉得有点迷失。

有人可以在这里指出不同语法的细节吗?谢谢!

3 个答案:

答案 0 :(得分:1)

基于错误:

错误的参数数量(2为0..1)

Rails(没有postgres)告诉你某个方法正在接收两个参数,但该方法只支持或不支持参数或只支持一个参数。

查看代码,发送两个参数的唯一两种方法是selectjoin,所以如果你尝试的话:

select('*, (case when viewid is null then 0, 1 end) as viewed')代替 select('*', '(case when viewid is null then 0, 1 end) as viewed')

和(仅用于测试,因为不良做法

  .join("left join views on(
       views.story_id = stories.id and view.user_id = #{user.id}
     )")

而不是

  .join('left join views on(
       views.story_id = stories.id and view.user_id = ?
     )', user.id)

答案 1 :(得分:0)

EXISTS(...)产生一个布尔值,它非常优雅地解决了NULL情况:

select s.*
  , EXISTS (select 42 from views v
            where v.story_id = s.id
            and v.user_id = 1) as viewed
from stories s
where 1=1
  ;

如果要在viewed子句中使用ORDER BY列,则必须将上述查询推送到子查询中。

答案 2 :(得分:0)

使用带条件的单个查询最接近postgres语法转换:

   select stories.*,
        CASE WHEN views.id is null THEN 0 ELSE 1 END as viewed
      from stories
      left join views
        on(views.story_id = stories.id and views.user_id = 1)
      where true
      group by stories.id, views.id
      order by viewed, stories.id