8

次の構造の MySQL データベース テーブルがあります。

table
    id INT NOT NULL PRIMARY KEY
    data ..
    next_id INT NULL

リンクされたリストの順序でデータを取得する必要があります。たとえば、次のデータがあるとします。

 id | next_id
----+---------
  1 |       2
  2 |       4
  3 |       9
  4 |       3
  9 |    NULL

id=1、2、4、3、9 の行をこの順序でフェッチする必要があります。データベースクエリでこれを行うにはどうすればよいですか? (私はクライアント側でそれを行うことができます。データベース側でこれを行うことができるかどうか興味があります。したがって、不可能だと言っても大丈夫です(十分な証拠があれば))。

終了ポイントもあると便利です (たとえば、10 回のフェッチの後、または行の条件が真になったときに停止します) が、これは必須ではありません (クライアント側で実行できます)。循環参照をチェックする必要がないことを願っています。

4

3 に答える 3

6

一部のブランドのデータベース(Oracle、Microsoft SQL Serverなど)は、「再帰クエリ」を実行するための追加のSQL構文をサポートしていますが、MySQLはそのようなソリューションをサポートしていません。

説明している問題は、SQLデータベースでツリー構造を表すのと同じです。あなたはただ長くて細い木を持っています。

この種のデータ構造をRDBMSから保存およびフェッチするには、いくつかのソリューションがあります。次の質問のいくつかを参照してください。


クエリによって返される「深さ」を制限したいということなので、次の方法でリストをクエリしているときにこれを実現できます。

SELECT * FROM mytable t1
 LEFT JOIN mytable t2 ON (t1.next_id = t2.id)
 LEFT JOIN mytable t3 ON (t2.next_id = t3.id)
 LEFT JOIN mytable t4 ON (t3.next_id = t4.id)
 LEFT JOIN mytable t5 ON (t4.next_id = t5.id)
 LEFT JOIN mytable t6 ON (t5.next_id = t6.id)
 LEFT JOIN mytable t7 ON (t6.next_id = t7.id)
 LEFT JOIN mytable t8 ON (t7.next_id = t8.id)
 LEFT JOIN mytable t9 ON (t8.next_id = t9.id)
 LEFT JOIN mytable t10 ON (t9.next_id = t10.id);

糖蜜のように機能し、結果はすべて1行に戻ります(リンクリストごと)が、結果は得られます。

于 2009-03-23T20:49:55.330 に答える
5

If what you are trying to avoid is having several queries (one for each node) and you are able to add columns, then you could have a new column that links to the root node. That way you can pull in all the data at once by the root id, but you will still have to sort the list (or tree) on the client side.

So in this is example you would have:

 id | next_id | root_id
----+---------+---------
  1 |       2 |       1
  2 |       4 |       1
  3 |       9 |       1
  4 |       3 |       1
  9 |    NULL |       1

Of course the disadvantage of this as opposed to traditional linked lists or trees is that the root cannot change without writing on an order of magnitude of O(n) where n is the number of nodes. This is because you would have to update the root id for each node. Fortunately though you should always be able to do this in a single update query unless you are dividing a list/tree in the middle.

于 2010-08-31T18:46:59.873 に答える
2

これは解決策ではなく、回避策ですが、線形リストの場合(Bill Karwinが言及したツリーではなく)、リストで並べ替え列を使用する方が効率的な場合があります。例えば:

TABLE `schema`.`my_table` (
    `id` INT NOT NULL PRIMARY KEY,
    `order` INT,
    data ..,
    INDEX `ix_order` (`sort_order` ASC)
);

それで:

SELECT * FROM `schema`.`my_table` ORDER BY `order`;

これには、挿入が遅いという欠点があります(ソートされたすべての要素を挿入ポイントを超えて再配置する必要があります)が、順序列にインデックスが付けられるため、検索は高速である必要があります。

于 2010-08-13T16:17:45.587 に答える