簡體   English   中英

MySQL多對多關系問題

[英]MySQL many to many relationship issue

我有三個表:articles,tags和articles_tags。 可以想象,每個文章可以有多個標簽,並且每個標簽可以分配給多個文章。 我有一個所謂的主要文章(用唯一的URL表示),並希望根據它們之間的共享標簽獲取相關文章,例如:如果主要文章和文章2具有一個共同的標簽,則同時顯示兩個文章(理想情況下,它不會在結果中顯示/不包含主要文章)。 在SQL查詢中傳遞主要文章的唯一URL。

預期的結果超出了我的能力范圍,因此我們將不勝感激。

SQLFiddle

復制的代碼(如果上述站點離線):

數據庫和內容:

CREATE TABLE `articles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `status` tinyint(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `tags` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tag` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `articles_tags` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `article_id` int(11) NOT NULL,
  `tag_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `articles` (`url`, `title`, `status`) VALUES
('test-article-1',  'Test Article #1',  1),
('test-article-2',  'Test Article #2',  1),
('test-article-3',  'Test Article #3',  0),
('test-article-4',  'Test Article #4',  0),
('test-article-5',  'Test Article #5',  1);

INSERT INTO `tags` (`tag`, `url`) VALUES
('Test',    'test'),
('City',    'city'),
('Nature',  'nature');

INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 2),
(3, 1),
(3, 2),
(4, 2),
(5, 1);

最新(無法正常工作)的SQL查詢:

SELECT
tags.tag,
articles.url,
articles.title
FROM articles
LEFT JOIN articles_tags ON articles_tags.article_id=articles.id
LEFT JOIN tags ON articles_tags.tag_id=tags.id
WHERE (articles.url='test-article-1'
    OR tags.id IN (articles_tags.tag_id))
    AND articles.status=1
GROUP BY articles.id

結果:如您在SQLFiddle上看到的,它顯示了文章1、2和5,但在我看來,它應該僅顯示1和5。

預期結果:第1條和第5條,理想情況下只有5條(不包括第1條,因為它是主要的)。

我不太確定我是否理解為什么您不希望第2條出現在您的結果中,因為它和第1條都帶有標記2。下面應該仍然返回第2條,因此它可能不是您想要的,但是我能想到的最直接的“類似標記的排名”查詢:

SELECT b.*, COUNT(1) AS tagMatches
FROM articles AS a
INNER JOIN articles_tags AS aTags ON a.id=aTags.article_id
INNER JOIN articles_tags AS bTags 
   ON aTags.article_id<>bTags.article_id 
   AND aTags.tag_id = bTags.tag_id
INNER JOIN articles AS b ON bTags.article_id
WHERE a.url = ?
GROUP BY b.url
ORDER BY tagMatches DESC, b.title
;

編輯:這假設文章不能多次使用相同的標簽。 如果不是這種情況,它將使排名傾斜(但是如果重復的標簽應具有更大的權重,則可能會比較有利)。

Edit2:值得注意的是, *可能不應用於最終結果; 我在這里只是為了簡單起見。

您的OR條件OR tags.id IN (articles_tags.tag_id))在以下行上觸發:

INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES
(1, 1),
 ...
(3, 1),
 ...,
(5, 1);

所以,對我來說結果看起來不錯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM