0

我在mysql中有3个表:

牌:

id  | name
1   | alpha
2   | beta

标签:

id  | name
1   | a
2   | b

标签链接:

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

我想检索所有不包含特定标签的卡片。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”。但是,由于 tag_link 中的一个条目将卡“2”与标签“1”连接起来,卡“2”也被错误地返回。

我想过使用上述函数获得第一个命中数组,然后在 php 中减去另一个数组,其中包含所有卡片,包括我不感兴趣的标签。但是这个解决方案感觉非常笨拙。解决这个问题最有效的方法是什么?

谢谢, 奇异果

4

3 回答 3

1

我对 CI 不太了解,但作为 SQL 查询,这可能有效(伪代码混合 SQL 和 php):

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

子查询返回包含某个标签的所有卡片 ID。然后主查询返回所有其他卡 ID。(请注意,子查询可能会导致非常大的表和/或复杂查询中的性能问题)

于 2013-10-03T22:48:34.807 回答
0

使用TheWolf的答案并将其转换为 active_record。记住 CI 不支持子查询(尽管可以使用库)

  $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');
于 2013-10-04T05:18:19.643 回答
0

首先你的表结构应该有明确的名称链接这个

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)

如您所见,您正在避免使用卡片 2,否则您一定会获得与任何 id 相关联的所有卡片,而不管您提供的 tag_id 较少。
是要测试的小提琴

于 2013-10-04T07:23:13.263 回答