2017-01-03 6 views
0

MySQLでgroup_concat()関数の正しい実行に問題があります。私はデータベースにアクションの対象となるエンティティを持っています。特定のアクションには処理の詳細が必要です。処理の詳細は処理のIDとして提供されます。私の処理内容は、いくつかの主要な処理の子と、これは私のクエリでmysqlのgroup_concat関数とwhere句で 'union'と 'in'を使用する

parent_id 

として表されるdBで、私は同じPARENT_IDを持つすべての子の処理によって処理されたすべてのエンティティのためのデータベースを求めているかもしれません私の開始エンティティの処理(私はすべての情報を事前に単一のエンティティを取得する)。データベースで

は、WHERE句は次のようになります。意図したとおり、私はselect句に()GROUP_CONCATを追加しようとするまで

where p.processing_id in 
    (SELECT processing_id FROM processing_type_1 where parent_id in 
     (select parent_id from processing_type_1 where parent_id in (p.processing_id))) 
     union all (SELECT processing_id FROM processing_type_2 where parent_id = 
      (select parent_id from processing_type_2 where parent_id in (p.processing_id))) 

この句は動作します。エンティティの各アクションには担当者が割り当てられており、すべての人に特定のアクションを割り当てる必要があります。

select句は次のようになります。

group_concat(distinct (select z.full_name from user z join entity_action ea on z.id = ea.personnel_id where ea.entity_id = e.id and ea.action_type = 'some_action' order by z.full_name) separator ', ') as action_personnel 

は、これは私がGROUP_CONCATにおけるサブクエリの終わり()で

limit 1 

を追加するまで、クエリが動作していないと述べました。行動に割り当てられた人が1人しかいない場合は問題にはなりませんが、残念なことに、そうではありません。

私の質問です - これらの2つの機能を実現する方法はありますか?

私の例のデータは以下のようになります。私はすべてのprocessin約尋ねた場合

entity_table

entity_id 
1 
2 
3 

entity_actionテーブル

action_id|entity_id| action_name|personnel_id|processing_id 
     1|  1|'some action'|   1|   15 
     2|  1|  'other'|   1| 
     3|  1| 'another'|   2| 
     4|  1|'some action'|   3|   17 

処理テーブル

processing_id|parent_id 
      15|  5 
      17|  5 

SELECT e.entity_id, 
group_concat(distinct (select z.full_name from user z join entity_action ea on z.id = ea.personnel_id where ea.entity_id = e.id and ea.action_type = 'some_action' order by z.full_name) separator ', ') as action_personnel 
FROM enity e 
inner join entity_action ea on ea.entity_id = e.entity_id 
left outer join processing p on p.id = ea.entity_id 
where 
(1 IS null OR 
p.processing_id in 
(SELECT processing_id FROM processing_type_1 where parent_id in 
    (select parent_id from processing_type_1 where parent_id in (p.processing_id))) 
    union all (SELECT processing_id FROM processing_type_2 where parent_id = 
     (select parent_id from processing_type_2 where parent_id in (p.processing_id))) 
) 
group by e.entity_id; 
+1

私たちにサンプル表データとあなたの期待される出力を示してください。 –

+1

これは非常に遅いクエリのようです。ネストされた 'IN'サブセレクトはおそらく私が想像できる最も遅いものです。私はクエリを再設計して、 'JOIN'を利用してより速く便利にすることができると思います。最初に改善するには、AS(エイリアス)を使用します。 – DanFromGermany

+0

完全なクエリを表示できますか?あなたがしようとしていることは、GROUP_CONCATの結果に対してINを使用することだと思います。 GROUP_CONCATは値のリストではなく文字列を返すため、これは機能しません。 – Kickstart

答えて

0

は一見の多くを持っていたこの場合は5私の望ましい結果のPARENT_IDを持つgsが

entity_id|action_personnel 
     1|    1,3 

次のように私の完全なクエリがあるだろうこれで今。あなたはGROUP_CONCAT内のSELECTでのサブクエリを持ってこれを見ると

SELECT e.entity_id, 
     GROUP_CONCAT((SELECT DISTINCT z.full_name FROM user z INNER JOIN entity_action ea ON z.id = ea.personnel_id WHERE ea.entity_id = e.id AND ea.action_type = 'some_action') ORDER BY full_name SEPARATOR ', ') AS action_personnel 
FROM enity e 
INNER JOIN entity_action ea ON ea.entity_id = e.entity_id 
WHERE (1 IS NULL 
OR p.processing_id in 
(
    SELECT processing_id 
    FROM processing_type_1 pt1_a 
    INNER JOIN processing_type_1 pt1_b 
    ON pt1_a.parent_id = pt1_b.parent_id 
    INNER processing p on p.id = ea.entity_id 
    ON pt1_b.parent_id = p.processing_id 
    UNION 
    SELECT processing_id pt2_a 
    FROM processing_type_2 
    INNER JOIN processing_type_2 pt2_b 
    ON pt2_a.parent_id = pt2_b.parent_id 
    INNER processing p on p.id = ea.entity_id 
    ON pt2_b.parent_id = p.processing_id 
) 
) 
GROUP BY e.entity_id; 

は、私はあなたが基本的なクエリは、このようなのIN句の一部を排除することができると思う(しかし、これは動作しません)。誰もこれを前に試してみたことはありませんでした。このマニュアルでは、GROUP CONCATで何も言及していません。しかし、私はそのような構文でプレーすると、SELECT内で複数の行を返すサブクエリがあるので、MySQLが混乱しているように見えます。これは、サブクエリにLIMIT 1を追加するときに動作し、サブクエリに1行を返すように強制するためです。

クリーンアップされたクエリで同じ問題が発生します。

これをクリーンアップして、メインクエリのユーザー操作とエンティティ操作を結合するだけで、データは特定できない場合があります。あなたは何ができるか

は、各ENTITY_IDのために一緒にグループ化されたすべてのフルネームを取得するには、サブクエリに対して結合です: -

SELECT e.entity_id, 
     sub1.action_personnel 
FROM enity e 
INNER JOIN entity_action ea ON ea.entity_id = e.entity_id 
INNER JOIN 
(
    SELECT ea.entity_id, 
      GROUP_CONCAT(DISTINCT z.full_name ORDER BY full_name SEPARATOR ', ') AS action_personnel 
    FROM user z 
    INNER JOIN entity_action ea 
    ON z.id = ea.personnel_id 
    WHERE ea.entity_id = e.id 
    AND ea.action_type = 'some_action' 
    GROUP BY ea.entity_id 
) sub1 
ON sub1.entity_id = e.id 
WHERE (1 IS NULL 
OR p.processing_id in 
(
    SELECT processing_id 
    FROM processing_type_1 pt1_a 
    INNER JOIN processing_type_1 pt1_b 
    ON pt1_a.parent_id = pt1_b.parent_id 
    INNER processing p on p.id = ea.entity_id 
    ON pt1_b.parent_id = p.processing_id 
    UNION 
    SELECT processing_id pt2_a 
    FROM processing_type_2 
    INNER JOIN processing_type_2 pt2_b 
    ON pt2_a.parent_id = pt2_b.parent_id 
    INNER processing p on p.id = ea.entity_id 
    ON pt2_b.parent_id = p.processing_id 
) 
) 
GROUP BY e.entity_id; 
+0

私の場合、内部結合を左結合に変更する必要がありました。これは、エンティティに処理が付加されていない可能性があるためです。それにもかかわらず、結合内のサブクエリは機能しているようです。 – Luigius

0

は、クエリを、次の試してみてください:

SELECT e.entity_id, 
GROUP_CONCAT(DISTINCT z.full_name ORDER BY z.full_name) SEPARATOR ', ') AS action_personnel 
FROM enity e 
INNER JOIN entity_action ea ON ea.entity_id = e.entity_id 
LEFT OUTER JOIN processing p ON p.id = ea.entity_id 
LEFT JOIN `user` z ON z.id = ea.personnel_id AND ea.action_type = 'some_action' 
WHERE 
(1 IS NULL OR 
p.processing_id IN 
(SELECT processing_id FROM processing_type_1 WHERE parent_id IN 
    (SELECT parent_id FROM processing_type_1 WHERE parent_id IN (p.processing_id))) 
    UNION ALL (SELECT processing_id FROM processing_type_2 WHERE parent_id = 
     (SELECT parent_id FROM processing_type_2 WHERE parent_id IN (p.processing_id))) 
) 
GROUP BY e.entity_id; 
関連する問題