SELECT `a`.*
FROM `articles` AS `a`
JOIN (
SELECT GROUP_CONCAT(DISTINCT `tag_id` ORDER BY `tag_id`) AS `tags`
FROM `articleTags`
WHERE `article_id` = :articleId
) AS `at`
JOIN (
SELECT GROUP_CONCAT(DISTINCT `tag_id` ORDER BY `tag_id`) AS `tags`, `article_id`
FROM `articleTags`
GROUP BY `article_id`
) AS `st` ON `st`.`article_id` = `a`.`id` AND `st`.`tags` = `at`.`tags`
CREATE FUNCTION is_tags_equal(article1 text, article2 text)
RETURNS boolean AS
$$
SELECT NOT EXISTS
(
(SELECT tag FROM articles_tags WHERE article = article1
EXCEPT
SELECT tag FROM articles_tags WHERE article = article2)
UNION ALL
(SELECT tag FROM articles_tags WHERE article = article2
EXCEPT
SELECT tag FROM articles_tags WHERE article = article1)
)
$$
LANGUAGE sql;
SELECT article FROM articles WHERE is_tags_equal(article, 'ArticleName') AND article != 'ArticleName';