2010-02-09 5 views
11

여기 내 문제가 있습니다. 나는 'user_has_personalities'라고 불리는 many-to-many 테이블을 가지고있다. 내 응용 프로그램에서는 사용자가 많은 특성을 가질 수 있으며 특성은 많은 사용자에게 속할 수 있습니다.MySQL 다 대다 질의 문제

테이블에는 user_id와 personality_id의 두 개의 정수 열이 있습니다.

내가해야 할 일은 내가 쿼리에 제공하는 적어도 모든 특성 (가변 크기의 personality_ids 집합)이있는 모든 사용자를 얻는 것입니다.

예를 들어, ID가 4, 5, 7 인 개성을 가진 모든 사용자를 얻고 싶지만 다른 인격을 가질 수도 있습니다. 하지만 예를 들어, 4, 5, 7, 9, 10과 같이 원하는 성격 ID의 가변 개수에 대해 작업 할 쿼리가 필요합니다.

아이디어가 있으십니까?

select user_id 
from user_has_personalities 
where personality_id in (<list-of-personality-ids>) 
group by user_id 
having count(*) = <numer-of-items-in-IN-list> 

당신은 <list-of-personality-ids>에 대한 성격 ID의 쉼표로 구분 된 목록을 제공해야하고 또한 일 elist의 항목 수를 제공해야합니다

답변

6

이 쿼리는 작업을 수행합니다. 귀하의 예를 따르면 다음과 같이 나타납니다.

select user_id 
from user_has_personalities 
where personality_id in (4,5,7) 
group by user_id 
having count(*) = 3 

이렇게하면 이러한 모든 특성을 가진 사용자 만 얻을 수 있습니다.

+0

이것은 단지 personality_id 중 하나인지 여부를 알려줍니다. 질문은 명시 적으로 모든 ID를 말합니다. –

+0

@Evan :이 쿼리는 사용자가 모든 ID를 가지고 있는지 여부를 알려줍니다. – Quassnoi

+0

나는 당신이하는 일을보고있다. 좋은. –

4
SELECT * 
FROM (
     SELECT DISTINCT user_id 
     FROM user_has_personalities 
     ) uhpo 
WHERE EXISTS 
     (
     SELECT NULL 
     FROM user_has_personalities uhpi 
     WHERE uhpi.user_id = uhpo.user_id 
       AND personality_id IN (4, 5, 6, 9, 10) 
     LIMIT 1 OFFSET 4 
     ) 

오프셋 값은 IN 목록에있는 항목의 수보다 1 이하이어야한다.

당신은 전용 테이블에서 당신의 성격 목록이있는 경우, 이것을 사용이 들어

SELECT * 
FROM (
     SELECT DISTINCT user_id 
     FROM user_has_personalities 
     ) uhpo 
WHERE (
     SELECT COUNT(*) 
     FROM perslist p 
     JOIN user_has_personalities uhpi 
     ON  uhpi.user_id = uhpo.user_id 
       AND uhpi.personality_id = p.id 
     ) = 
     (
     SELECT COUNT(*) 
     FROM perslist 
     ) 

을 올바르게 (빠른) 작업, 당신은 (이 순서대로) user_has_personalities (user_id, personality_id)UNIQUE 인덱스가 있어야합니다. 이 목록을 생성 할 수있을만큼 쉬운 것입니다

SELECT user_id 
FROM users uhpo 
WHERE (
     SELECT COUNT(*) 
     FROM perslist p 
     JOIN user_has_personalities uhpi 
     ON  uhpi.user_id = uhpo.user_id 
       AND uhpi.personality_id = p.id 
     ) = 
     (
     SELECT COUNT(*) 
     FROM perslist 
     ) 
+0

+1 일반의 숙련도와 마법사 성 : 콰스 노니, 당신의 블로그를 사랑합니다. 나는 당신의 블로그를 더욱 열렬히보고 싶습니다만, 그곳에 코멘트를 남기려한다면 분명히 당신의 특권을 그대로 두십시오. 어쨌든, 환호하고 계속 지켜라. –

+0

@Roland : 'Miscellaneous'카테고리의 모든 기사에 댓글이 달려있다. – Quassnoi

+0

확인, 공정하게 충분 :) 감사합니다. –

1
SELECT a.user_id 
FROM user_has_personalities a 
JOIN user_has_personalities b ON a.user_id = b.user_id AND b.personality_id = 5 
JOIN user_has_personalities c ON a.user_id = c.user_id AND b.personality_id = 7 
WHERE a.personality_id = 4 

:

당신이 users 테이블과 거의 모든 사용자가있는 경우 user_has_personalities의 기록을 가지고, 다음 DISTINCT 중첩 된 쿼리의 장소에 대체 프로그래밍 방식으로 제공되지만 세트를 제공하는 것만 큼 쉽지는 않습니다. 반면에, 그것은 효율적입니다.