gpt4 book ai didi

mysql - 如何查询多对多连接并过滤相同的关系?

转载 作者:行者123 更新时间:2023-11-29 01:10:17 25 4
gpt4 key购买 nike

我简化了一个多对多关系的案例使用这些模型表。

Posts:
------------------------------
| id | title | body |
------------------------------
| 1 | One | text1 |
| 2 | Two | text2 |
| 3 | Three | text3 |
------------------------------

Tags:
-------------------
| id | name |
-------------------
| 1 | SQL |
| 2 | GLSL |
| 3 | PHP |
-------------------

Post_tags:
------------------------------
| id | p_id | t_id |
------------------------------
| 1 | 1 | 1 |
| 2 | 1 | 3 |
| 3 | 2 | 1 |
| 3 | 3 | 2 |
------------------------------

我的目标是查询带有特定标签的帖子,我对此没有问题,但我也想显示帖子的所有相关标签,而不仅仅是我查询的标签。我的查询如下所示:

SELECT p.Title, p.Body, t.name
FROM Posts p
LEFT JOIN Post_tags pt ON p.id = pt.p_id
LEFT JOIN Tags t ON t.id = pt.t_id
WHERE t.name LIKE '%SQL%'

这会获取带有“SQL”标签的帖子,但它只会在找到“SQL”字符串的位置加入带有标签的帖子表,因此不会加入与帖子关联的其他标签“PHP”。

显然问题是我在 WHERE 子句上连接表,但是如何在一个查询或(最好使用子查询)中解决这个问题?

目前,我在我的应用程序中的两个独立查询中执行此操作,一个用于选择匹配的帖子,另一个用于检索完整的帖子数据。这不是那么有效,而且似乎是一个蹩脚的解决方案,而且我还没有找到更好的解决方案,所以我决定询问 StackOverflow 社区。

最佳答案

我的 old answer不是最短的,这是最短的:

select p.*, '' as x, t.name, t.name like '%SQL%'
from Posts p
join Posts_tags pt on pt.p_id = p.id
join Tags t on t.id = pt.t_id;

输出:

ID  TITLE   BODY    X       NAME    T.NAME LIKE '%SQL%'
1 One text1 SQL 1
1 One text1 PHP 0
2 Two text2 SQL 1
3 Three text3 GLSL 0

因此,如果我们按 ID 分组,并检查组中的元素是否至少有一个(借助于 bit_or;Postgresql 也有这个,恰本地命名为 bool_or)满足 '%SQL%' 条件,它的位为 ON (又名 bool 值 = 真)。我们可以选择该组并保留该组下的所有标签,例如,标签 id 1 出现在帖子 1 上,而帖子 1 有其他标签,即 #3 或 PHP。属于同一帖子 ID 的所有标签都不会被丢弃,因为我们不会使用 WHERE 过滤器,我们将使用 HAVING 过滤器:

select p.*, group_concat(t.name) as tags
from Posts p
join Posts_tags pt on pt.p_id = p.id
join Tags t on t.id = pt.t_id
group by p.id
having bit_or(t.name like '%SQL%');

我们也可以将其重写为:

select p.*, group_concat(t.name) as tags
from Posts p
join Posts_tags pt on pt.p_id = p.id
join Tags t on t.id = pt.t_id
group by p.id
having sum(t.name like '%SQL%') >= 1;

BIT_OR 类似于 INANY,因此它比通过 SUM 求值更具语义。 p>

输出:

D   TITLE   BODY    TAGS
1 One text1 PHP,SQL
2 Two text2 SQL

现场测试:http://www.sqlfiddle.com/#!2/52b3b/26


我在 stackoverflow 上学到了很多东西。在我的旧答案之后,我正在考虑如何通过 SUM OVER partition 使用窗口函数(MySQL 没有)在 Postgresql 中制作一个等效的较短代码。然后想到了Postgresql的bool_or,bool_andevery函数。然后我记得 MySQL 有 bit_or :-)

最后一个使用 SUM 的解决方案只是事后的想法,当我想到 bit_or 只是 至少一个为真 的语义时,那么显然您也可以使用 HAVING SUM(condition) >= 1。现在它适用于所有数据库:-)

我最终没有通过窗口函数解决它,上面的解决方案现在适用于所有数据库:-)

关于mysql - 如何查询多对多连接并过滤相同的关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10469884/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com