2010-02-22 6 views
2

두 개의 테이블이 있습니다. 하나는 items이고 하나는 tags입니다. 검색어의 hereMysql Join Query는 동일한 결과를 여러 번 제공합니다.

아이디어는 검색 상자를 만들어 항목을 검색 한 다음 태그를 선택하여 검색 범위를 좁히는 것입니다. (어떤 종류의 패싯 검색).

MySQL의 자습서와 주변 하구 후 나는이 함께했다 :

SELECT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`) 
WHERE (
    (`tags`.`type`='food' AND `tags`.`name`='pizza') 
    OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
    --And so on for every tag 
) 
ORDER BY `pay` DESC LIMIT 0 , 30 

는 (필자는 쿼리의 전체 텍스트 검색을 제거 그것은 지금 관련되지 않기 때문에)

그것은 꽤 작동 사용자가 어떤 태그를 선택하지 않는 경우, 더 후 1 개 태그가 모든 항목에 부착

  1. 더 후 1 시간
  2. ,369을 보여줍니다 좋은,하지만 난이 문제가
  3. 사용자가 food => pizza and drinks => 예를 들어 레모네이드라는 두 개의 태그를 선택하면 피자 나 레모네이드가있는 모든 항목 또는 두 가지 모두가 표시됩니다. 태그가 첨부 된 항목 만 필요합니다.

다른 mysql 쿼리로 이러한 문제를 해결할 수 있습니까? 아니면 PHP 코드에서 이러한 문제를 해결해야합니다. (아니면 완전히 잘못하고 있는데, 태그를 사용하는 것이 더 나은 방법일까요?)

잘하면 나는 분명히했습니다.

할머니,

바스

답변

2

던져 IN tag.id?

SELECT DISTINCT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`) 
WHERE ( 
    (`tags`.`type`='food' AND `tags`.`name`='pizza') 
    OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
    --And so on for every tag 
) 
ORDER BY `pay` DESC LIMIT 0 , 30 

두 번째 문제는 ... 논리가 잘못되었습니다. 내가 제대로 이해하면 당신은 items.id로 그룹화 할 그리고 아마 뭔가 같은 선택 태그의 수 ... 같은 동일한 행 번호와 돌아 오지 않는 항목 거부 :

SELECT DISTINCT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
    FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`) 
    WHERE ( 
     (`tags`.`type`='food' AND `tags`.`name`='pizza') 
     OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
     --And so on for every tag 
    ) 
    GROUP BY `items`.`id` 
    HAVING COUNT(*) = 2 
    ORDER BY `pay` DESC LIMIT 0 , 30 

을 ... HAVING COUNT (*) = 2의 2를 동시에 일치시키려는 태그의 수로 대체하십시오 ...

+0

감사합니다. 마지막 쿼리가 완벽하게 작동했습니다! – Bas

+0

Btw,이 좋은 mysql 연습입니까? – Bas

+0

정말 대답하기 어려운 질문입니다 ...성능에 관한 한 적절한 인덱스를 설정하는 한 괜찮을 것입니다. 제 의견으로는 올바르게 일관되게 작동하고 응용 프로그램에 '충분히 빠릅니다'라고 대답하면됩니다. – vicatcu

1

한번에 위치를 선택 후 키워드 DISTINCT에서 (하위 쿼리)

SELECT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
FROM `items` WHERE items.id IN (SELECT DISTINCT item_id 
    FROM tags 
    WHERE (
    (`tags`.`type`='food' AND `tags`.`name`='pizza') 
    OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade')) 
    --And so on for every tag 
) 
ORDER BY `pay` DESC LIMIT 0 , 30 
+0

이렇게하면 복제 된 결과의 문제는 해결되지만 사용자가 1 개 이상의 태그를 선택하면, 두 태그가있는 항목을 반환하지 않습니다. 대신 선택한 태그 중 하나를 사용하여 모든 항목을 반환합니다. 어떤 아이디어? – Bas

+0

피자와 레모네이드가있는 상품 만 원한다면 OR을 AND로 변경하십시오. 이것은 vicatcu의 방법에도 적용됩니다. 원하는 경우 태그 수를 세지 않아도됩니다. – MindStalker

+0

그건 작동하지 않습니다. 모든 태그/유형 조합에는 고유 한 행이 있습니다. 따라서 SELECT DISTINCT item_id FROM 태그 여기에 ('tags'.type' = '음식'AND'tags'.name' = '피자') AND ('tags'.type' = 'drinks 'AND' tags'.name' ='lemonade ')) 한 행에 두 개의 값과 이름을 저장할 수 없으므로 결과를 반환하지 않습니다. – Bas

관련 문제