2

テーブル構造

id    |    message    |    reply_id
1     |    help me!   |    0
434   |    love to    |    1
852   |    didn't work |    434
0110  |    try this   |    852
2200  |    this wont  |    0
5465  |    done. :)   |    0110

ツリーメニューの中央にあるID「852」がありますが、前の関連行と次の関連行をすべて取得したいので、次のような結果を取得したいと思います。

助けて!>大好き>うまくいかなかった>これを試してみてください>完了しました。:)(この結果は、phpループの後のように表示されますが、応答ID0のスターターID1からループを開始します。

注:2200 idはグループの一部ではないため、結果には表示されませんでした。

4

3 に答える 3

3

階層情報を SQL で扱いやすくするには、いくつかの方法があります。

  • 共通テーブル式(SQL-2003 標準による) は、使用している親 ID タイプのデータに対する再帰的な SQL クエリをサポートします。これまでのところ、MySQL はこの機能をサポートしていません。PostgreSQL 8.4、Microsoft SQL Server、および IBM DB2 は、CTE 構文をサポートする RDBMS ブランドの例です。Oracle には、再帰クエリをサポートする SQL 構文に対する独自の拡張機能もあります。

  • ネストされたセット(@phantombrain が言及している左/右のソリューション) は、Joe Celko の著書「Trees and Hierarchies in SQL for Smarties」や、インターネット上の多数の記事やブログ投稿で詳述されているソリューションです。

  • パスの列挙(別名マテリアライズド パス) は、階層内の各行に文字列を格納して、その行の先祖のパスを記録します。これをクエリと組み合わせてLIKE、パス文字列をその祖先のパスおよび子孫のパスと比較します。

  • Closure Table (別名 Transitive Closure Relation) は、2 番目のテーブルを使用して、使用している設計のように直接の親だけでなく、すべての先祖と子孫の関係を格納します。すべてのパスを保存すると、多くの種類のクエリが簡単になります。

  • ハイブリッド ソリューションも存在します。たとえば、現在行っているように直接の親 ID を保存するだけでなく、ツリーのルートも保存します。これで、同じ階層内の他のすべての行を取得し、それらをアプリケーション コードにフェッチして、従来のデータ構造でツリーを並べ替えることができます。

于 2009-08-11T00:47:28.813 に答える
1

これらがメニュー項目であり、フォーラムなどの非常に動的なものではないと仮定すると、各項目に左右の値を追加するようにスキーマを変更することをお勧めします。左と右の値の間のIDは、クエリしているノードのすべての子です。したがって、1つのクエリを実行して左/右の値を取得し、2番目のクエリを実行してサブアイテムを取得するのは簡単です。

詳細については、 http://www.sitepoint.com/print/hierarchical-data-database/を参照してください。

于 2009-08-11T00:14:43.487 に答える
0

再帰はこれを行うための最も洗練された方法ですが、mySql がカスタム関数またはストアドプロシージャでサポートしているとは思いません。一時テーブルまたはテーブル変数にループして ID を取得し、テーブルを結合して結果をクエリすることをお勧めします。私はmySqlをよく知らないので、これはテストされていませんが、この効果には何かがあります。

CREATE TEMPORARY TABLE tbl (myid int, ViewOrder int); 
Set @ifoundID=IdYourLookingFor;
Set @iStartID=@ifoundID;
Set @iOrder=0;
INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);

BEGIN --get the ones going up
 WHILE (@ifoundID Is Not Null) DO 
  SELECT @ifoundID=reply_id FROM YourTable WHERE id=@ifoundID; --find the next id
  SET @iOrder1=@iOrder-1; --increment the order
  INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);--save the nextid
 END WHILE;
END

Set @ifoundID=@iStartID;
BEGIN --get the ones going down
 WHILE (@ifoundID Is Not Null) DO 
  SELECT @ifoundID=id FROM YourTable WHERE reply_id=@ifoundID; --find the next id
  SET @iOrder1=@iOrder+1; --increment the order
  INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);--save the nextid
 END WHILE;
END

SELECT * FROM tbl INNER JOIN YourTable ON tbl.myid=YourTable.id ORDER BY ViewOrder

それが役立つことを願っています

于 2009-08-11T00:48:49.113 に答える