查询 M:N 包含
Posted
技术标签:
【中文标题】查询 M:N 包含【英文标题】:Query M:N contains 【发布时间】:2018-03-07 00:58:38 【问题描述】:我正在尝试过滤一组表,其中包括 android Room (SQLite) 中的 M:N 联结表。
一张图片可以有很多主题。我想允许按主题过滤,以便获得包含完整图像信息(包括所有主题)的行。因此,如果一张图片有(国家公园,优胜美地)对其中任何一个进行过滤,则会导致一行包含两个关键字。除非我搞砸了,否则典型的连接会产生多行,这样匹配的Yosemite
会得到正确的图像,但你会缺少National Park
。我想出了这个:
SELECT *,
(SELECT GROUP_CONCAT(name)
FROM meta_subject_junction
JOIN subject
ON subject.id = meta_subject_junction.subjectId
WHERE meta_subject_junction.metaId = meta.id) AS keywords,
(SELECT documentUri
FROM image_parent
WHERE meta.parentId = image_parent.id ) AS parentUri
FROM meta
现在这让我得到了完整的行,但我认为此时我需要:
WHERE keywords LIKE(%YOSEMITE%)
我认为LIKE
不太理想,更不用说不精确的匹配了。有没有更好的方法来实现这一点?谢谢,这让我的新手 SQL 大脑受不了了。
更多详情
meta
+----+----------+--+
| id | name | |
+----+----------+--+
| 1 | yosemite | |
| 2 | bryce | |
| 3 | flowers | |
+----+----------+--+
subject
+----+---------------+--+
| id | name | |
+----+---------------+--+
| 1 | National Park | |
| 2 | Yosemite | |
| 3 | Tulip | |
+----+---------------+--+
junction
+--------+-----------+
| metaId | subjectId |
+--------+-----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
| 3 | 3 |
+--------+-----------+
虽然我可能做错了什么,但据我所知 Android Room 不喜欢:
+----+-----------+---------------+
| id | name | subject |
+----+-----------+---------------+
| 1 | yosemite | National Park |
| 1 | yosemite | Yosemite |
+----+-----------+---------------+
所以我正在尝试减少行数:
+----+-----------+-------------------------+
| id | name | subject |
+----+-----------+-------------------------+
| 1 | yosemite | National Park, Yosemite |
+----+-----------+-------------------------+
上面的查询所做的。但是,我也想查询一个主题。这样National Park
过滤器就会产生:
+----+-----------+-------------------------+
| id | name | subject |
+----+-----------+-------------------------+
| 1 | yosemite | National Park, Yosemite |
| 2 | bryce | National Park |
+----+-----------+-------------------------+
我想比 LIKE 更精确/更高效,因为已经是“concat”主题。我的大多数尝试都以在 Room(多行)中没有结果或将主题减少到仅过滤器关键字而告终。
更新
这是我一直在使用的一个测试,用于将查询的实际 SQL 结果与 Android Room 的最终结果进行比较:
http://sqlfiddle.com/#!7/0ac11/10/0
该连接查询被解释为 Android Room 中的四个对象,因此我试图减少行数,但在过滤包含主题关键字的任何图像时保留完整的主题结果。
【问题讨论】:
请提供一些示例数据和您想要的输出。 (有关如何添加一些内容,请参阅How to format SQL tables in a Stack Overflow post?。) 【参考方案1】:如果要多个关键字,则可以使用where
和group by
和having
:
select image_id
from image_subject
where subject_id in ('a', 'b', 'c') -- whatever
group by image-id
having count(distinct subject_id) = 3; -- same count as in `where`
【讨论】:
对不起,我不清楚。我认为这是在寻找匹配的多个(全部或没有)主题。如果我误读了那对不起。我正在匹配具有我要过滤的任何主题的任何图像(不需要拥有所有主题)。我遇到的问题(我认为)是 Android Room (ORM) 似乎需要由单行表示的对象,所以我需要匹配Yosemite
以产生一行与“国家公园、优胜美地等."。或者也许 group by 正在那里做那个魔术并且某种具有 > 1 的东西会起作用?
所以稍微玩一下那个查询,你是否暗示我会使用那个查询在第二个查询中创建一个where meta.id IN ([your query result])
,因为这给了我一个 id 结果集?换句话说,这将是一个两个交易过程吗?【参考方案2】:
这得到了我需要的结果,但如果效率特别低,我很想听到更好的选择。
SELECT meta.*,
(SELECT GROUP_CONCAT(name)
FROM junction
JOIN subject
ON subject.id = junction.subjectId
WHERE junction.metaId = meta.id) AS keywords,
junction.subjectId
FROM meta
LEFT JOIN junction ON junction.metaId = meta.id
WHERE subjectId IN (1,2)
GROUP BY meta.id
+----+----------+------------------------+-----------+
| id | name | keywords | subjectId |
+----+----------+------------------------+-----------+
| 1 | yosemite | National Park,Yosemite | 2 |
| 2 | bryce | National Park | 1 |
+----+----------+------------------------+-----------+
http://sqlfiddle.com/#!7/86a76/13
【讨论】:
以上是关于查询 M:N 包含的主要内容,如果未能解决你的问题,请参考以下文章
从有序矩阵M x N中找出是否包含某一个数,要求时间复杂度为O(M+N)
python使用matplotlib可视化subplots绘制子图自定义几行几列子图,如果M行N列,那么最终包含M*N个子图在指定的子图中添加可视化结果
考虑页面置换算法,系统有m个物理块供调度,初始时全空,页面引用串长度为p,包含了n个不同的页号,无论用什么算法,缺页次数不会少于( )