Mysql

如何檢查 tag_map GROUP By article_id 中是否存在兩個標籤?

  • July 23, 2022

在一個相當簡單tag_map

CREATE TABLE tag_map
(
article_id int(11) unsigned NOT NULL,
tag_id int(11) unsigned NOT NULL,
INDEX(tag_id),
PRIMARY KEY(article_id,tag_id)
) ENGINE=InnoDB;

如何檢查哪些文章具有此表中給出的標籤對?

CREATE TABLE tag_pairs
(
pair_id int(11) unsigned NOT NULL,
tag1 int(11) unsigned NOT NULL,
tag2 int(11) unsigned NOT NULL,
UNIQUE INDEX(tag1,tag2),
INDEX(tag2),
PRIMARY KEY(pair_id)
) ENGINE=InnoDB;

在範例小提琴中,預期的輸出是:

SELECT article_id,pair_id FROM ... (how to JOIN here)

1    5
1    7
3    6

效率是最重要的,因為桌子很大。

由於tag_map相當大,我避免JOIN在它本身。目前,我SELECT對每個pair_id,

SELECT article_id, 5 
FROM tag_map 
 WHERE tag_id IN(22,23) 
 GROUP BY article_id 
 HAVING SUM(IF(tag_id=22,1,0))>0 AND SUM(IF(tag_id=23,1,0))>0;

這不是有效的。

您的問題是這個問題的一種變體:How to filter SQL results in a has-many-through relationship。閱讀這個問題以及解決這個有趣問題的許多(和不同的)方法。

令人驚訝的是,您的更普遍的問題有一個更簡單的解決方案 - 它涉及三角連接:

select
   t1.article_id,
    p.pair_id
from 
   tag_map as t1
 join
   tag_map as t2
     on  t1.article_id = t2.article_id
 join
   tag_pairs as p
     on  p.tag1 = t1.tag_id
     and p.tag2 = t2.tag_id ;
SELECT m1.article_id, m1.tag_id, m2.tag_id
   FROM tag_map AS m1
   JOIN tag_pairs AS p  ON p.tag1 = m1.tag_id
   JOIN tag_map AS m2   ON p.tag2 = m2.tag_id
   WHERE m2.article_id = m1.article_id;

我將 tag_pairs 更改為

UNIQUE INDEX(pair_id),
INDEX(tag2),
PRIMARY KEY(tag1,tag2)

但我寧願完全擺脫pair_id。

引用自:https://dba.stackexchange.com/questions/314703