2013-05-14 3 views
1

나는 이것이 쉬운 질문이지만 내 MySQL 찹은 약간 녹슬지는 않을 것이라고 생각한다. 여러 조건부 조인을 사용하여 다음 시나리오에 대한 적절한 쿼리를 생성하는 데 약간의 도움이 필요합니다. 나는 하나의 테이블에 속성 (태그를 생각하는)과 다른 테이블에 레코드 목록을 가지고있다. 쿼리에 하나 이상의 속성이 정의 된 페이지와 일치시키려는 경우 문제가 발생합니다.다중 조건부 연결

+--------------------------------------+ 
| ATTRIBUTES       | 
+-----------+------------+-------------+ 
| name  | value  | page_id  | 
+-----------+------------+-------------+ 
| type  food   2   | 
| fruit  apple  2   | 
| color  green  2   | 
| type  frog   3   | 
| color  green  3   | 
+--------------------------------------+ 


+--------------------------------------+ 
| PAGES        | 
+--------------+-----------------------+ 
| page_id  | title     | 
+--------------+-----------------------+ 
| 2    Granny Smith   | 
| 3    Kermit the Frog  | 
+--------------------------------------+ 

사용 사례

Query: type+food 
Results: Granny Smith 

Query: color+green 
Results: Granny Smith, Kermit the Frog 

Query: type+food and color+green 
Results: Granny Smith 

이것은 내가 놀고 있었는데 쿼리는하지만, 분명히 작동하지 :

SELECT page.page_id, page.title 
FROM page_attributes 
LEFT JOIN page ON (page_attributes.page_id = page.page_id) 
WHERE (page_attributes.name = 'color' 
AND page_attributes.value = 'green') 
AND (page_attributes.name = 'type' 
AND page_attributes.value = 'food') 
+0

시도한 SQL을 알려주십시오. –

+1

어떤 쿼리가 작동하지 않습니까? –

+1

당신이 원하는 결과 만 원한다면 전혀 참여할 필요가 없습니다. – luksch

답변

0

Nitro와 동일한 줄에는 ON 절이있는 속성에 대한 기준이 있습니다. 또한 조인을 최적화 할 수 있도록 특성 테이블의 인덱스 (page_id, name, value)가 있는지 확인하십시오.

SELECT 
     page.page_id, 
     page.title 
    FROM 
     page 

     INNER JOIN page_attributes a1 
      ON page.page_id = a1.page_id 
      AND a1.name = 'color' 
      AND a1.value = 'green' 

     INNER JOIN page_attributes a2 
      ON page.page_id = a2.page_id 
      AND a2.name = 'type' 
      AND a2.value = 'food' 

    LIMIT 10 

위에서 볼 수 있듯이 전체 "조인"을 복사/지나치게 다른 "기준"을 추가하려고합니다. 일치하는 것을 발견하고 포함 시키거나 허용하지 않으며 페이지 레코드를 무시합니다.

+0

완벽하고 자동화하기 쉽도록 작동합니다. 감사. –

+0

@ 루위 와우, 자동화에 관심이있는 것 같아요. 그렇습니다. 여러 번 조인하고 WHERE 절을 조정하는 것이 더 쉽습니다. 그러나 두 가지 솔루션 모두 좋은 옵션입니다. – DRapp

2

한 가지 방법은이 일을, 더있을 수 있습니다 경우에도 효율적인 방법은 각 속성에 대해 하나씩 복수 INNER JOIN 인 쿼리를 작성하는 것입니다. INNER JOIN 인 경우 LEFT JOIN과 대조적으로 주 행이 일치하려면 모든 조건이 true 여야합니다.

SELECT page.page_id, page.title 
    FROM page 
INNER JOIN page_attributes a1 ON (a1.page_id = page.page_id) 
INNER JOIN page_attributes a2 ON (a2.page_id = page.page_id) 
WHERE (a1.name = 'color' AND a1.value = 'green') 
    AND (a2.name = 'type' AND a2.value = 'food') 
LIMIT 10 
0

모든 조인을 다른 조인 행에 동시에 적용하려고하면 문제가 발생합니다.

Joined relation: 
+--------------+-----------------------+-------------+-------------+ 
| page_id  | title     | name  | value  | 
+--------------+-----------------------+-------------+-------------+ 
| 2    Granny Smith   type   food  | 
| 2    Granny Smith   color   green  | 
| 2    Granny Smith   fruit   apple  | 
| 3    Kermit the Frog   color   green  | 
| 3    Kermit the Frog   type   frog  | 
+--------------+-----------------------+-------------+-------------+ 

이 절은이 중간 결과의 각 행에 적용 할 WHERE : 다음과 같이 (모든 SELECT 또는 WHERE 필터링 전) 조인 관계가 어떤 식거야. 따라서 쿼리의 절 :

WHERE (page_attributes.name = 'color' 
AND page_attributes.value = 'green') 
AND (page_attributes.name = 'type' 
AND page_attributes.value = 'food') 

은 연결된 관계의 각 행에 대해 false가됩니다.

간단히 ANDOR으로 변경하면 태그 값이 모두있는 페이지가 아닌 모든 페이지 값을 검색하기 만하면되므로 실제로 쿼리를 수행 할 수 있습니다.

불행하게도이 테이블 구조에는 쿼리되는 임의의 수의 태그에 대해이를 수행하는 일반적인 표준화 된 방법이 없습니다. 얼마나 많은 태그가 쿼리 될지 미리 아는 경우 page_attributes 테이블에 여러 조인을 사용하는 다른 대답의 제안이 유용하며 여러 개의 UNION ed 쿼리와 비슷한 효과를 얻을 수 있습니다. 하지만 다시 말하지만, 쿼리 할 태그의 수를 고치면 작동합니다.

최소 복잡한 일반 솔루션은 SQL에서 모든 작업을 수행하지 않는 것입니다. 조인 및 태그 값에 종속되지 않는 모든 WHERE 조건을 수행 한 다음 응용 프로그램 코드가 결과에 대해 반복 코드를 작성하고 태그 쿼리 논리를 적용하게하십시오.