【问题标题】:Rails/SQL help: three tables, select and sort by presence of another recordRails/SQL 帮助:三个表,根据是否存在另一条记录进行选择和排序
【发布时间】:2018-05-30 05:51:20
【问题描述】:

使用 ActsAsTaggableOn gem,可标记对象是模板。 加上这些关联:

class Template
  acts_as_taggable
  has_many :template_designs
end

class Pins
  belongs_to :template
  belongs_to :tag
end

class Tags
  has_many :taggings
end

目标:准备分页的模板集合,在用户选择标签的地方,我们找到与该标签匹配的所有模板,并根据 pin 中是否存在相同的标签和模板对它们进行排序,顶部为 true。

编辑 - 简化和释义。

鉴于模板带有标签,并且这些标签可能有也可能没有 Pin,我需要选择所有带有 X 标签的模板,并对它们进行排序,无论该标签是否有一个 Pin(布尔排序,顶部为真) .

【问题讨论】:

  • 请分享示例数据,查询您尝试过的和想要的输出。

标签: sql ruby-on-rails activerecord rails-activerecord querying


【解决方案1】:

一种方法是将外连接与CASE WHEN EXISTS 表达式一起使用:

select templates.*, case when exists 
  (select pins.id 
    from pins 
    where pins.tag_id = tags.id 
    and pins.template_id = templates.id) then true else false end as pinned 
  from templates, taggings, tags, pins 
  where templates.id = taggings.template_id 
  and taggings.tag_id = tags.id 
  and tags.name = 'funny';

这是一个 Active Record 语法:

>> Template.left_outer_joins(:tags)
.where(tags: {name: 'funny'})
.select(:id, :name, 
"case when exists 
  (select pins.id from pins 
  where pins.tag_id = tags.id 
  and pins.template_id = templates.id)
  then true else false end as pinned")
.map {|t| [t.id, t.name, t.pinned] }
[... sql output ...]
=> [[1, "template1", true], [2, "template2", false]]

【讨论】:

  • 以各种方式尝试了这种方法,但对我来说并不奏效。没有指定我正在使用的数据库,即 Postgres,它不喜欢 Case When 返回值的别名。此外,将该方法应用于这个更简单的查询,并且 order by 没有起作用:SELECT id, total FROM orders ORDER BY CASE WHEN EXISTS (SELECT id, total FROM orders WHERE orders.total > 100000) THEN true ELSE false END
  • 我现在正在研究动态查询生成来解决这个有趣的问题。不过,感谢您的帮助。
  • @bazfer 我很惊讶这种情况/当构造不适合你时......我也在使用 Postgres (9.6),但我可能误解了架构。我添加了我正在使用的架构,欢迎更正。
  • 它有效!只需要添加'ORDER BY pinned DESC'。感谢一万亿。
  • 哦,很好,你是对的@bazfer 我忘记了 ORDER 子句。听起来不错!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多