将记录表与负关系上的映射表连接起来

时间:2018-06-15 09:43:48

标签: mysql inner-join

假设我有两个表recordtag,其中record包含大量详细信息,tag只包含记录与标签,即

tag包含以下列:

tag        ENUM 'SomeTagA','SomeTagB','SomeTagC' NOT NULL
record_id  INT NOT NULL

组合(tagrecord_id)是唯一的。

现在,我可以使用(INNER)JOIN:

轻松查询正面关系
SELECT r.*
FROM record AS r
JOIN tag AS t1 ON t1.record_id = r.id AND t1.tag = "SomeTagA"
JOIN tag AS t2 ON t2.record_id = r.id AND t2.tag = "SomeTagB"

然而,如果我想否定第三个标签怎么办?比如,选择所有包含标签A和标签B但不包含标签C的记录。我能想出的唯一解决方案是:

SELECT r.*
FROM record AS r
WHERE (SELECT COUNT(*) FROM tag WHERE tag = "SomeTagA" and record_id = r.id) = 1
  AND (SELECT COUNT(*) FROM tag WHERE tag = "SomeTagB" and record_id = r.id) = 1
  AND (SELECT COUNT(*) FROM tag WHERE tag = "SomeTagC" and record_id = r.id) = 0

但我可以想象这是一个有点慢的解决方案。

1 个答案:

答案 0 :(得分:2)

您可以使用条件聚合来满足您的条件

SELECT r.col1, r.col2
FROM record AS r
JOIN tag AS t ON t.record_id = r.id
GROUP BY r.col1, r.col2
HAVING SUM(t.tag = 'SomeTagA') > 1
AND SUM(t.tag = 'SomeTagB') > 1
AND SUM(t.tag = 'SomeTagC') = 0

SUM(t.tag = 'SomeTagA')可以表示为SUM(CASE WHEN t.tag = 'SomeTagA' THEN 1 ELSE 0 END),在mysql中使用sum和一些像sum(a = b)这样的表达式将得到一个布尔值,你将得到一个基于你的表达式的计数