23

私は次のようなテーブルを持っています:

+------+---------+-
| id   | parent  |
+------+---------+
| 2043 |    NULL |
| 2044 |    2043 |
| 2045 |    2043 |
| 2049 |    2043 |
| 2047 |    NULL |
| 2048 |    2047 |
| 2049 |    2047 |
+------+---------+

これは、単純な2レベルの「親子」相関関係を示しています。SELECTステートメントでORDERを実行して、上記のリストのような順序を取得するにはどうすればよいですか。つまり、第1の親、第1の親の子、第2の親、第2の親の子などです(これがある場合は、子供のための注文者...私は願っています)。ソートフィールドを追加せずに可能ですか?

4

4 に答える 4

64

IDによる子の並べ替えを含む:

ORDER BY COALESCE(parent, id), parent IS NOT NULL, id

SQLフィドルの例

説明:

  • COALESCE(parent, id):最初に、親のIDで(効果的にグループ化して)並べ替えます。
  • parent IS NOT NULL:親行をグループの一番上に配置します
  • id:最後にすべての子を並べ替えます(同じ親であり、parentnullではありません)
于 2012-11-14T16:02:46.230 に答える
6

テーブルが0代わりにを使用nullして、親のないエントリを示す場合:

id   | parent
-------------
1233 | 0
1234 | 1233
1235 | 0
1236 | 1233
1237 | 1235

greatestの代わりに使用coalesceして、値が等しくないことを確認してください0

ORDER BY GREATEST(parent, id), parent != 0, id
于 2017-12-29T21:32:45.260 に答える
3

上記の解決策は私にはうまくいきませんでした、私のテーブルはNULLの代わりに0を使用しました。この別の解決策を見つけました。クエリで親IDと子IDを連結して列を作成し、それで結果を並べ替えることができます。

SELECT CONCAT(IF(parent = 0,'',CONCAT('/',parent)),'/',id) AS gen_order
FROM table 
ORDER BY gen_order
于 2018-04-13T13:19:09.030 に答える
2

この質問は、まだ最初の検索結果の1つとして表示されます。だから私は私の解決策を共有したいと思います、そしてそれがより多くの人々を助けることを願っています。これは、多くのレベルの親子関係を持つテーブルがある場合にも機能します。それはかなり遅い解決策ですが。トップレベルはNULL親として持っています。

+---------+---------+
| id      | parent  |
+---------+---------+
| 1       | NULL    |
| 2       | 1       |
| 3       | 1       |
| 4       | 2       |
+---------+---------+

id私のアプローチでは、再帰的に自分自身を呼び出し、要求された親に到達するまで、要求された親のパスの前にパスを追加し続けるプロシージャを使用しますNULL

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `PATH`(IN `input` INT, OUT `output` VARCHAR(128))
BEGIN

  DECLARE _id INT;
  DECLARE _parent INT;
  DECLARE _path VARCHAR(128);

  SET `max_sp_recursion_depth` = 50;

  SELECT `id`, `parent`
  INTO _id, _parent
  FROM `database`.`table`
  WHERE `table`.`id` = `input`;

  IF _parent IS NULL THEN
    SET _path = _id;
  ELSE
    CALL `PATH`(_parent, _path);
    SELECT CONCAT(_path, '-', _id) INTO _path;
  END IF;

  SELECT _path INTO `output`;

END $$
DELIMITER ;

句で結果を使用するには、の結果をラップORDER BYするtooも必要になります。FUNCTIONPROCEDURE

DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `GETPATH`(`input` INT) RETURNS VARCHAR(128)
BEGIN

  CALL `PATH`(`input`, @path);
  RETURN @path;

END $$
DELIMITER ;

これで、再帰パスを使用してテーブルの順序を並べ替えることができます。10000行のテーブルでは、ワークステーションで1秒強かかります。

SELECT `id`, `parent`, GETPATH(`id`) `path` FROM `database`.`table` ORDER BY `GETPATH`(`id`);

出力例:

+---------+---------+---------------+
| id      | parent  | path          |
+---------+---------+---------------+
| 1       | NULL    | 1             |
| 10      | 1       | 1-10          |
| 300     | 10      | 1-10-300      |
| 301     | 300     | 1-10-300-301  |
| 302     | 300     | 1-10-300-302  |
+---------+---------+---------------+
5 rows in set (1,39 sec)
于 2021-07-31T20:15:48.630 に答える