sql - 使用连接表过滤用户
问题描述
我有用于用户、标签和连接表标签的表。
我目前正在使用scope
通过不同的变量过滤用户,例如:
scope = scope.where('users.created_at > :created_after', created_after: params[:created_after])
我正在尝试通过分配给他们的标签(通过has many
关系)过滤用户。
在用户模型中:
has_many :taggings, as: :taggable
has_many :tags, through: :taggings
用户表:
╔════╦══════════════╦
║ id ║ name ║
╠════╬══════════════╬
║ 1 ║ Picard ║
║ 2 ║ Kirk ║
║ 3 ║ Sisko ║
║ 4 ║ Janeway ║
╚════╩══════════════╩
标签表:
╔════╦══════════════╦
║ id ║ Tag ║
╠════╬══════════════╬
║ 1 ║ TOS ║
║ 2 ║ TNG ║
║ 3 ║ DS9 ║
║ 4 ║ VOY ║
╚════╩══════════════╩
标记表:
╔════╦═══════════╦═══════════════╦═══════════════════════╦
║ id ║ tag_id ║ taggable_id ║ taggable_type ║
╠════╬═══════════╬═══════════════╬═══════════════════════╣
║ 1 ║ 1 ║ 1 ║ User ║
║ 2 ║ 1 ║ 4 ║ Organization ║
║ 3 ║ 2 ║ 2 ║ User ║
║ 4 ║ 1 ║ 3 ║ User ║
╚════╩═══════════╩═══════════════╩═══════════════════════╝
我试过类似的东西:
SELECT * FROM users u
JOIN taggings j, tags t
WHERE t.tag = <tag>
AND t.id = j.tag_id
AND j.taggable_type = 'User'
AND u.id = j.taggable_id
解决方案
您可以获得计数并使用必须规定用户必须具有一个或多个标签:
tags = ["TOS", "TNG"]
User.joins(:tags)
.where(tags: { tag: tags })
.group(:id)
.having(
# Arel for "COUNT(tags.*) >= ?"
Tag.arel_table[Arel.star].count.gte(tags.length)
)
由于您使用的是多态关联,因此您可能希望将其烘焙到一个模块中,以便您可以重用它:
module Taggable
extend ActiveSupport::Concern
included do
has_many :taggings, as: :taggable
has_many :tags, through: :taggings
end
class_methods do
def with_tags(*tags)
joins(:tags)
.where(tags: { tag: tags })
.group(:id)
.having(
Tag.arel_table[Arel.star]
.count.gteq(tags.length)
)
end
end
end
class User < ApplicationRecord
include Taggable
end
推荐阅读
- ios - 在 iOS 模拟器中从 firebase 推送通知
- java - Java Streams 功能转换/丰富数据
- r - 当所有变量都不显着时,逐步回归会崩溃循环
- snowflake-cloud-data-platform - Snowflake 编译器错误的解决方法
- java - Maximo where 子句 SQL 注入
- android - 如何避免这些乏味的 findViewById() 调用?
- php - 用户在 Laravel 中使用 Redis 加入广播频道后,在后端获取事件
- github - 如何在 github repo 代码中搜索带前导 & 符号的字符串
- c# - 如何使用 C# 将 xml 文件合并到一个具有两个特定节点的文件中
- flutter - 带有键盘的 Flutter TextFieldForm 导致重建