2

小さな (できれば) MySQL の質問に頭を悩ませることはできません。リンクと呼ばれるテーブルがあります。これには、customer_id フィールドとlinked_id フィールドが含まれ、基本的に、customer_id が先頭にある顧客アカウントを相互にリンクします。新しく作成されたアカウントは、アカウント自体を生成できます。ログオンしたユーザーによって作成されたすべてのアカウントと、サブアカウントによって作成されたすべてのアカウントを確認したいと思います。

表は次のようになります。

+----+-------------+-----------+
| id | customer_id | linked_id |
+----+-------------+-----------+
|  1 |           1 |         5 |
|  2 |           1 |         2 |
|  3 |           1 |        11 |
|  4 |           1 |        13 |
|  5 |          13 |        14 |
|  6 |           3 |         4 |
|  7 |           7 |         8 |
+----+-------------+-----------+

したがって、customer_id 1 のユーザーとしてログインしている場合、linked_id 5,2,11,13 (直接接続であるため) および linked_id 14 (このユーザーは、 1)に直結。

すべてのユーザーの詳細を取得するには、クエリをサブクエリにする必要があります。私は現在持っています:

SELECT username, firstname, lastname, email, active, level FROM customers WHERE id
IN (SELECT linked_id FROM links WHERE customer_id=1) or id=1;

これは明らかに、直接接続と id=1 を持つユーザーのみを直接返します。

4

1 に答える 1

1

私を正しい軌道に乗せてくれたeggyalに感謝します。相対的な複雑さを見て、最初から解読できなかったほど恥ずかしいとは感じなくなりました。

最終的にいくつかの調査を行ったところ、mysql でクロージャー テーブルを使用するための優れたセットアップがいくつか見つかりました。最終的に、クロージャ テーブルと、もちろん新しいテーブル cust_closure を設定するためのストアド プロシージャを作成しました。リンクテーブルによって名前を cust_links に変更しました。

cust_links:

+-------------+---------+------+-----+---------+----------------+
| Field       | Type    | Null | Key | Default | Extra          |
+-------------+---------+------+-----+---------+----------------+
| id          | int(11) | NO   | PRI | NULL    | auto_increment |
| customer_id | int(11) | YES  |     | NULL    |                |
| linked_id   | int(11) | YES  |     | NULL    |                |
+-------------+---------+------+-----+---------+----------------+

cust_closure:

+-------------+---------+------+-----+---------+-------+
| Field       | Type    | Null | Key | Default | Extra |
+-------------+---------+------+-----+---------+-------+
| customer_id | int(11) | YES  |     | NULL    |       |
| linked_id   | int(11) | YES  |     | NULL    |       |
| distance    | int(11) | YES  |     | NULL    |       |
+-------------+---------+------+-----+---------+-------+

次に、ストアド プロシージャを追加しました。

CREATE PROCEDURE populate_cust_closure()
BEGIN
  DECLARE distance int;
  TRUNCATE TABLE cust_closure;
  SET distance = 0;
  -- seed closure with self-pairs (distance 0)
  INSERT INTO cust_closure (customer_id, linked_id, distance)
    SELECT customer_id, customer_id, distance
      FROM cust_links GROUP BY customer_id;

  -- for each pair (root, leaf) in the closure,
  -- add (root, leaf->child) from the base table
  REPEAT
    SET distance = distance + 1;
    INSERT INTO cust_closure (customer_id, linked_id, distance)
      SELECT cust_closure.customer_id, cust_links.linked_id, distance
        FROM cust_closure, cust_links
          WHERE cust_closure.linked_id = cust_links.customer_id
          AND cust_closure.distance = distance - 1;
  UNTIL ROW_COUNT()=0
  END REPEAT;
END // 

次にストアド プロシージャを呼び出すと、次のように生成されました。

mysql> select * from cust_closure;
+-------------+-----------+----------+
| customer_id | linked_id | distance |
+-------------+-----------+----------+
|           1 |         1 |        0 |
|           3 |         3 |        0 | 
|           7 |         7 |        0 | 
|          13 |        13 |        0 | 
|           1 |         5 |        0 |
|           1 |         2 |        0 |
|           1 |        11 |        0 |
|           1 |        13 |        0 |
|          13 |        14 |        0 |
|           1 |        14 |        1 |
|           3 |         4 |        0 |
|           7 |         8 |        0 |
+-------------+-----------+----------+

したがって、元のクエリは次のようになります。

SELECT username, firstname, lastname, email, active, level FROM customers WHERE id
IN (SELECT linked_id FROM cust_closure WHERE customer_id=1);

再びeggyalに感謝し、これが将来誰かに役立つことを願っています.

于 2013-07-15T13:24:56.730 に答える