먼저 제목이 이해가되지 않는다면 미안하지만 더 나아질 수는 없습니다. 나는 비슷한 질문을 찾으려고했지만, 나를 도울 수있는 어떤 것도 찾지 못했습니다.MySQL 다중 태그 선택
간략한 설명 :
나는 제품의 데이터베이스가 있습니다. 제품에 여러 개의 태그가 있습니다. 사용 가능한 태그가있는 제품을 필터링하고 싶습니다. 이미 작동하고있는 솔루션이 있지만 표에 40k 행만있는 약점이 있습니다. 기본 쿼리를 최적화하고 싶기 때문에 결국에는 나를 해치지 않습니다.
태그 항목의 관계 표 :
CREATE TABLE `tags_assoc` (
`assoc_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`tag_id` int(10) unsigned NOT NULL,
`item_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`assoc_id`),
KEY `tag_id` (`tag_id`),
KEY `item_id` (`item_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
페이지가 작동하도록되어 방법 :
태그의 거대한 목록이 있습니다. 사용자가
tag_id
을 선택하고 페이지가 필터링되어item_id
에 특정 태그tag_id
이 표시됩니다.백엔드는 필터링 된
item_id
을 검사하고 추가 필터링에 사용할 수있는tag_id
을 모두 나열합니다.
에 Query1 - 상품의 목록 :이
SELECT
item_id,
count(tag_id) as count
FROM
tags_assoc
WHERE
tag_id IN (...)
GROUP BY
item_id
HAVING
count = (...)
QUERY2이 - 나머지 태그 목록 :
SELECT
ta.tag_id,
t.tag_name,
COUNT(ta.tag_id) as count
FROM
tags_assoc ta
LEFT JOIN
tags t ON (ta.tag_id = t.tag_id)
WHERE
AND item_id IN (...)
AND ta.tag_id NOT IN (...)
GROUP BY
ta.tag_id
작동 원리 :
가의가에 가정 해 봅시다 우리가 선택하는 첫 라운드 tag_id = 250
. 즉, Query1에는 WHERE tag_id IN (250)
및 HAVING count = 1
이 포함됩니다. 반환 된 목록에는 다음과 같은 item_ids 1, 2, 3, 4, 5
이 포함됩니다.
나머지 태그를 얻으려면 다음 매개 변수를 사용하여 Query2를 실행하십시오. AND item_id IN (1, 2, 3, 4, 5) AND ta.tag_id NOT IN (250)
.
사용자는 남은 태그에서 다른 태그를 선택합니다 (예 : tag_id = 300
). 즉, Query1에는 WHERE tag_id IN (250, 300)
및 HAVING count = 2
이 포함됩니다. 반환 된 목록에는 다음 항목이 포함됩니다. 1, 2, 3
.
나머지 태그를 얻으려면 다음 매개 변수를 사용하여 Query2를 실행하십시오. AND item_id IN (1, 2, 3) AND ta.tag_id NOT IN (250, 300)
.
문제는 :
사용자가 첫 번째 태그를 선택하고, 반환 된 ITEM_ID 목록은 상당히 길어질 수 있습니다. 즉, Query2는 다음을 포함 할 수 있으므로 길어집니다. AND item_id IN (1, 2, 3, ... 7500, 7501, 7502)
. 37k 문자의 긴 검색어가 있습니다. 성능에 관해서는, 그것은 끔찍하지는 않지만 딸꾹질을 일으킬 수 있습니다. 그리고 이것은 항목 테이블과 40k 행에서만 7k 행과 함께 있습니다.
은 이미 시도했다 : AND item_id IN (SELECT item_id FROM tags_assoc WHERE tag_id IN (...) GROUP BY item_id HAVING COUNT(tag_id) = (...))
:
내가 긴 ITEM_ID 목록을 포함, 대신 훨씬 Query1을에서처럼 하위 쿼리를 사용하지 QUERY2를 다시 썼다. 성과가 현명했기 때문에이 대안을 포기했습니다.
누군가 나를 더 나은 방향으로 안내 할 수 있습니까?
긴 게시물을 작성해 주셔서 진심으로 사과드립니다.
고맙습니다! 이 메소드의 문제점은 여러 개의 tag_ids와 함께 표시됩니다. 예를 들어 쿼리 1은 다음과 같이 보일 것입니다 : SELECT DISTINCT item_id FROM tags_assoc ta WHERE ta.tag_id IN (250, 300)'. ** item_id에 ** ** 태그 중 적어도 하나를 나열합니다. ** ** 모든 ** 태그가있는 item_ids를 나열하고 싶습니다. 당신의 방법은 선택을 넓히고, 제 방법은 그것을 좁 힙니다. 적어도 이것이 내가 그것을 해석하는 방법이다. – user523736
죄송합니다, 저의 실수 - HAVING 절을 설명합니다! – Alan
저는 임시 테이블을 사용하여 제안 할 답변을 변경했습니다. 이렇게해도 문제가 해결되지 않으면 본인의 질문을 오해하여이 답변을 삭제할 투표를하겠습니다. – Alan