2013-10-03 5 views
0

CI 활동 기록을 사용하여 특정 태그와 관련된 DB 항목을 제외하는 방법 :내가 3 개 MySQL의에서 테이블을 가지고

카드 :

id | name 
1 | alpha 
2 | beta 

태그 :

id | name 
1 | a 
2 | b 

tag_link :

id | card | id 
1 | 1  | 1 
2 | 2  | 1 
3 | 2  | 2 

모든 차량을 검색하고 싶습니다. ds는 특정 태그를 포함하지 않습니다. CI 모델 :

function search($_tag) { 
    $this->db->select('card.id'); 
    $this->db->join('tag_link', 'card.id = tag_link.card'); 

    $this->db->where_not_in('tag_link.tag', $_tag); 

    $this->db->group_by('card.id'); 
    $query = $this->db->get('card'); 
    return $query; 
} 

태그 '2'의 경우 예상대로 '1'카드를 반환합니다. 그러나 카드 '2'는 '2'태그와 '1'태그를 연결하는 tag_link의 한 항목 때문에 잘못 반환됩니다.

나는 위의 함수를 사용하여 첫 번째 배열 배열을 얻은 다음, 관심이없는 태그를 포함한 모든 카드를 포함하는 PHP의 다른 배열을 뺍니다. 그러나이 솔루션은 매우 어색함을 느낍니다. 이 문제에 대해 가장 효율적인 접근 방법은 무엇입니까?

감사합니다, singultus

+0

을 테스트하는 바이올린입니다 active_record –

답변

0

TheWolf의 대답을 사용하여 active_record로 변환하십시오. 모든

$this->db->select('id'); 
    $this->db->where('id NOT IN (SELECT card FROM tag_link WHERE tag IN $tags)', NULL, FALSE); 
    $query = $this->db->get('cards'); 
+1

거의 완벽한, 단지 : $ this-> db-> where ('ID NOT IN (선택 카드 FROM tag_link WHERE tag IN'. $ tags. ')', NULL, FALSE); ' – singultus

1

내가 CI에 대해 너무 많이 알고하지 않습니다하지만, SQL 쿼리로,이 작동 할 수 있습니다 (SQL와 PHP를 혼합 의사 코드) :

SELECT id 
FROM cards 
WHERE id NOT IN 
(
    SELECT card FROM tag_link WHERE tag IN $tags 
) 

하위 쿼리 반환 특정 태그가 포함 된 모든 카드 ID 그런 다음 기본 쿼리는 다른 모든 카드 ID를 반환합니다. 하위 쿼리는 매우 큰 테이블 및/또는 복잡한 쿼리에서 성능 문제를 일으킬 수 있습니다.

+1

에서 아래 해결 방법을 시도해보십시오. – singultus

+0

나는 이미 upvoted했습니다 :) –

0

먼저 (라이브러리를 사용할 수 있지만) 하위 쿼리 CI가 지원하지 않는 기억 테이블 구조는 그런 다음에와 조건을 넣을 수 있습니다 분명히 이름이

cards: 
------- 
id | name 
1 | alpha 
2 | beta 

tags: 
------ 
id | name 
1 | a 
2 | b 

tag_link: 
--------- 
id | card_id | tag_id 
1 | 1   | 1 
2 | 2   | 1 
3 | 2   | 2 

를 연결해야 다른 결과를 피하십시오. 회피 카드를 제공하십시오. 그렇지 않으면 대답하는 질문은 쓸모가 없다.

function search($tag_id,$card_id) { 
    return $this->db 
     ->select('card.id')  
     ->from('tag_link') 
     ->join('card','card.id = tag_link.card_id','INNER') 
     ->where_not_in('tag_link.tag_id',$_tag) 
     ->where_not_in('tag_link.card_id',$card_id) 
     ->get() 
     ->result_array() 
} 

이렇게하면이 쿼리가 생성됩니다.

SELECT 
    card.id 
FROM tag_link 
    INNER JOIN card 
    ON card.id = tag_link.card_id 
WHERE tag_link.tag_id NOT IN(2) 
    AND tag_link.card_id NOT IN(2) 

당신은 현명한 당신이 어떤 ID에 연결되어있는 모든 카드를 얻을 수밖에 카드 다른 2을 피할 수있다시피 어쨌든 귀하가 제공하는 tag_id의 적은 간주한다. 난 당신이 일반적인 접근 방식을 제공 나도에서 +1을받을 것입니다 필요한 명성을 가지고 있다면
Here가 당신에게 내가 추측 결과를 얻을 것이다 가입 제거

+0

필자가 알기로는 솔루션에서 제외 할 카드 ID를 미리 알아야 할 것입니다 (함수의 param).이것이 검색 엔진에 포함되기 때문에 어떤 카드가 제외하고 싶은 카드 옆에 다른 태그가 있는지 모릅니다. 그러나 하위 쿼리가없는 솔루션이 유리할 수 있습니다. – singultus

+0

추신 : 실제로 제안 된 방식대로 열 이름이 지정됩니다. 짧은 이름은 mwe의 부산물이었습니다. – singultus

관련 문제