我有下表:
create_table "report_tags", force: true do |t|
t.integer "report_id"
t.string "tag", limit: 20
t.datetime "created_at"
t.datetime "updated_at"
end
该表格包含以下内容:
+----+-----------+--------+
| id | report_id | tag |
+----+-----------+--------+
| 1 | 1 | foo |
| 2 | 1 | bar |
| 3 | 2 | foo |
| 4 | 2 | bar |
| 5 | 2 | foobar |
| 6 | 3 | foo |
| 7 | 3 | t2 |
+----+-----------+--------+
如果用户给我一个字符串,其中包含一些我需要在特定报告中找到的标签。
换句话说,如果用户向我提供String "foo,bar"
我想要返回report_id 1,因为这是具有标签foo和bar的那个。
是否可以使用Mysql查询执行此操作?由于我的应用程序使用Active Record作为持久性框架,因此可以使用Active Record更容易吗?
PS:用户可以提供任意数量的标签
答案 0 :(得分:2)
如果仅允许用户按顺序输入搜索条件,则以下内容将起作用:
SELECT mq.report_id
FROM
(
SELECT t.report_id, GROUP_CONCAT(t.tag ORDER BY t.id SEPARATOR ',') AS ConcatTag
FROM MyTable AS t
GROUP BY t.report_id
) AS mq
WHERE mq.ConcatTag = 'foo,bar'
以下内容也适用:
SELECT t.report_id, GROUP_CONCAT(t.tag ORDER BY t.id SEPARATOR ',') AS ConcatTag
FROM MyTable AS t
GROUP BY t.report_id
HAVING GROUP_CONCAT(t.tag ORDER BY t.id SEPARATOR ',') = 'foo,bar'
以下是展示上述内容的SQL Fiddle。
答案 1 :(得分:1)
以下SQL查询可以找到那些指定了所有标记<{>> EDIT:而没有其他}的report_id
。我想不出将其翻译成AREL的方法,但仍然有一种更简单的方法。
SELECT report_id, SUM(contribute) as sum FROM
(SELECT DISTINCT report_id, tag, 1 as contribute FROM report_ids
WHERE tag IN ('foo', 'bar')
UNION
SELECT DISTINCT report_id, tag, -1 as contribute FROM report_ids
WHERE tag NOT IN ('foo', 'bar'))
GROUP BY report_id HAVING sum = 2;
(2,当然,是您要搜索的不同标签的数量)
答案 2 :(得分:0)
ReportTag.select(:id).where(tag: 'foo')