2017-07-31 4 views
0

candidates,candidate-skillsおよびskillsのMySqlテーブルがあります。 すべてのスキルを持った候補者を選択する最善の方法GROUP_CONCATを使用してすべてのスキルを持つ候補を選択してください

次のクエリを使用してみました。しかし、それは正確ではありません。

私が欲しいものを二点は以下のとおりです。すべてのスキルを持つ

  • レコード(のWHERE条件をコメントする場合)

    1. すべてのスキルが示されるべき示すことになっています。 (1つのスキルを持つレコードも、配列内のどこを使用しているかを示しています)

    私はcodeigniterフレームワークを使用しています。

    http://sqlfiddle.com/#!9/b75c3/49

  • 答えて

    1

    。 CodeIgniterの

    //take all skill ids in array 
    $ids=['8','10']; 
    $this->db->select("t.*"); 
    $this->db->select("GROUP_CONCAT(DISTINCT(s.name)) as skills"); 
    $this->db->select("GROUP_CONCAT(DISTINCT(s.id)) as skill_ids"); 
    $this->db->from("candidates t"); 
    $this->db->join("candidate-skills cs","t.id = cs.can_id"); 
    $this->db->join("skills s","cs.skill_id = s.id"); 
    $this->db->group_by("t.id"); 
    foreach ($ids as $id) { 
    $this->db->having("find_in_set ('$id', skill_ids)"); 
    } 
    $this->db->order_by("t.id","desc"); 
    $query=$this->db->get(); 
    $candidates=$query->result(); 
    
    0

    たぶん代わりに使用句を持つところのこの

    select t.* , 
         s.skills,s.skills_id 
    FROM `candidates` `t` 
    join 
    (
    select t.id tid, group_concat(s.name) skills, group_concat(s.id order by s.id) skills_id 
    FROM `candidates` `t` 
    LEFT JOIN `candidate-skills` `cs` ON `t`.`id` = `cs`.`can_id` 
    LEFT JOIN `skills` `s` ON `cs`.`skill_id` = `s`.`id` 
    group by t.id 
    ) s 
    on s.tid = t.id 
    where instr(skills_id,'8,10') > 0 
    
    +----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+ 
    | id | name   | created_on   | modified_on | is_deleted | skills         | skills_id | 
    +----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+ 
    | 1 | Eugine   | 2017-05-23 11:44:30 | NULL  | N   | zend framework 2,bootstrap,wordpress  | 8,10,12  | 
    | 2 | Frinoy Francis | 2017-05-23 16:44:29 | NULL  | N   | html,html5,zend framework 2,php,bootstrap | 1,4,8,10,11 | 
    +----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+ 
    2 rows in set (0.03 sec) 
    
    MariaDB [sandbox]> select t.* , 
        -> s.skills,s.skills_id 
        -> FROM `candidates` `t` 
        -> join 
        -> (
        -> select t.id tid, group_concat(s.name) skills, group_concat(s.id order by s.id) skills_id 
        -> FROM `candidates` `t` 
        -> LEFT JOIN `candidate-skills` `cs` ON `t`.`id` = `cs`.`can_id` 
        -> LEFT JOIN `skills` `s` ON `cs`.`skill_id` = `s`.`id` 
        -> group by t.id 
        ->) s 
        -> on s.tid = t.id 
        -> where instr(skills_id,'') > 0 
        -> ; 
    +----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+ 
    | id | name   | created_on   | modified_on | is_deleted | skills         | skills_id | 
    +----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+ 
    | 1 | Eugine   | 2017-05-23 11:44:30 | NULL  | N   | zend framework 2,bootstrap,wordpress  | 8,10,12  | 
    | 2 | Frinoy Francis | 2017-05-23 16:44:29 | NULL  | N   | html,html5,zend framework 2,php,bootstrap | 1,4,8,10,11 | 
    | 3 | Arun   | 2017-05-28 12:56:24 | NULL  | N   | bootstrap         | 8   | 
    +----+----------------+---------------------+-------------+------------+-------------------------------------------+-------------+ 
    3 rows in set (0.03 sec) 
    
    +0

    解決策はありますが、依然として問題があります。スキルIDは5,6,7,8であり、私たちが望むのは5と7です。この状態ではこの解決法は機能しません。 –

    +0

    あなたはwhere条件を分割し、それぞれのskill_idに対してandと結合することができます。 –

    1

    複数に参加使用される最も柔軟な方法で

    select `t`.*, GROUP_CONCAT(DISTINCT(s.name)) as skills, 
    GROUP_CONCAT(DISTINCT(s.id)) as skill_ids 
    FROM `candidates` `t` 
    LEFT JOIN `candidate-skills` `cs` ON `t`.`id` = `cs`.`can_id` 
    LEFT JOIN `skills` `s` ON `cs`.`skill_id` = `s`.`id` 
    GROUP BY `t`.`id` 
    having find_in_set ('8', skill_ids) and find_in_set ('10', skill_ids) 
    ORDER BY `t`.`id` desc 
    

    。 GROUP_CONCATとコンマで区切られたリストは反パターンとみなされ、連結が正確な順序で正確に行われていないと機能しない可能性があります(スキルセット1,2,5は1,5,2と同じではないとみなされます)。

    SELECT c.* FROM candidates AS c 
        JOIN candidateskills AS cs ON (cs.cand_id = c.id) 
        JOIN skills AS sk1 ON (cs.skill_id = sk1.id) 
        JOIN skills AS sk2 ON (cs.skill_id = sk2.id) 
        ...other sk(N)... 
        WHERE (sk1.skill = 'waterskiing') 
         AND (sk2.skill = 'snowboarding') 
         ... 
        ; 
    

    例えば、各スキルは、スキルレベルがあり、このような柔軟性レベル5で以上の熟練するスノーボードのために必要がある場合、これはスキルの容易な調整を可能にするには、GROUP_CONCATを行うには地獄です。

    しかし、単純なマッチングのために、あなたが望むスキルを選択し、ちょうどそれらをカウントすることにより、より速くそれを行うことができます。

    SELECT c.* FROM candidates AS c 
        JOIN candidateskills AS cs ON (cs.cand_id = c.id) 
        WHERE cs.skill_id IN (1, 7, 24, 19, 115) 
    GROUP BY c.id 
    HAVING COUNT(1) = 5; 
    

    (より適切なSQLでは、あなたがCの明示的にすべてのフィールドを示す代わりにする必要があるだろう"c。*"をGROUP BY句で繰り返します。より巧妙なRDBMSサーバは、cのプライマリキーでグループ化する限り、気にしません。現在は、とにかく気にしませんが、厳密なモードではそうです)。

    スキルごとに、スキルについてIDを取得し、上記のクエリを組み立てるためのスキルについて1つの高速クエリを実行します。

    それとも、限り、あなたはスキルと完全に一致していて、単一の、より大きなクエリで行うことができます:あなたはPHPでこれをしたいので

    SELECT c.* FROM candidates AS c 
        JOIN candidateskills AS cs ON (cs.cand_id = c.id) 
        JOIN skills AS s ON (cs.skill_id = s.id) 
        WHERE s.skill IN ('javascript', 'html5', 'php') 
    GROUP BY c.id 
    HAVING COUNT(1) = 3; 
    

    を:それは良いです

    $skills = array('javascript', 'html5', 'php'); 
    
    $skno = count($skills); 
    $set = implode(',', array_fill('?', $skno)); 
    $params = $skills; 
    $params[] = $skno; 
    
    $query = "SELECT c.* FROM candidates AS c 
        JOIN candidateskills AS cs ON (cs.cand_id = c.id) 
        JOIN skills AS s ON (cs.skill_id = s.id) 
        WHERE s.skill IN ({$set}) 
    GROUP BY c.id 
    HAVING COUNT(1) = ?"; 
    
    $stmt = $db->prepare($query); 
    $stmt->execute($params); 
    while ($candidate = $stmt->fetch(PDO::FETCH_ASSOC)) { 
        ... 
    } 
    
    関連する問題