Rails/SQL 帮助:三个表,select 并按是否存在另一条记录进行排序
Rails/SQL help: three tables, select and sort by presence of another record
使用 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
目标:一组准备好分页的模板,其中用户 selects 一个标签,我们找到所有与该标签匹配的模板,并根据是否存在相同的标签和模板对它们进行排序,如果为真在上面。
编辑 - 简化和释义。
鉴于模板带有标签,并且这些标签可能有也可能没有 Pin,我需要 select 所有带有 X 标签的模板,并根据该标签是否有 Pin(布尔值)对它们进行排序排序,真在上)。
一种方法是将外部联接与 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]]
使用 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
目标:一组准备好分页的模板,其中用户 selects 一个标签,我们找到所有与该标签匹配的模板,并根据是否存在相同的标签和模板对它们进行排序,如果为真在上面。
编辑 - 简化和释义。
鉴于模板带有标签,并且这些标签可能有也可能没有 Pin,我需要 select 所有带有 X 标签的模板,并根据该标签是否有 Pin(布尔值)对它们进行排序排序,真在上)。
一种方法是将外部联接与 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]]