あなたは、単一のデータベースを照会するために、「騎士の移動」を使用して、それ自体に参加することはできますか?

ニールHutcheon:

私は同じ問題を解決するためのプロローグとSQLの両方のコードを必要とするプロジェクトに取り組んでいます。私は全体の実行した問題は、私は階層構造を形成するために、単一のデータベースを使用することはできませんです。プロローグ事実のこのリストでは、「組立」の部分が互いに関連していることがわかります。

basicpart(spoke).
basicpart(rearframe).
basicpart(handles).
basicpart(gears).
basicpart(bolt).
basicpart(nut).
basicpart(fork).

assembly(bike,[wheel,wheel,frame]).
assembly(wheel,[spoke,rim,hub]).
assembly(frame,[rearframe,frontframe]).
assembly(frontframe,[fork,handles]).
assembly(hub,[gears,axle]).
assembly(axle,[bolt,nut]).

私は1つのSQLデータベースにこれらの「組立」の定義のすべてを置けば、私は2つのテーブルにSQLでこの階層を構築するために騎士を移動する(その中に2つの異なる列にテーブルをそれ自体に参加)を使用できますか?

デビッドTonhofer:

私は正確にその質問を理解していれば。あなただけの1クエリ(私は用語「騎士の動き」に精通していないよ)で、あなたのバイクを構築することができません。実際には、次のことができます-それはでなければなりません再帰SQLクエリあなたはパート・サブパート関係の推移閉包を計算されますので。

残念ながら、私はすぐにこれらの書き方を知りません。SQL構文でもabysmallerので、下記の代わりにループを使用したサンプルコードで率直ひどいと再帰SQLのルックスです。

あなたが実際としてデータを表現するために1つのテーブルのみを必要とするbasicpart/1関係が基本としてラベル特定の「もの」を除いて、表には何も持っていません。しかし、これらはまた、中に表示されていないものassembly/2最初の位置に。

ノート:

  • 実際のMySQL / MariaDBの「種類」ではありませんが、特定のテーブルのフィールドにだけ制約ENUMSを使用していません。(同様に、WTF!)
  • マルチセットプロローグコード(「自転車は、2つの車輪を有している」)の表現は、別途数値サロゲートIDによって識別される複数の行に平坦化されます。これは、に起因して、「第1正規形 RDBMSの練習の」ドグマ。クエリ言語とRDBMSエンジンがそれをサポートできる場合、値として多重集合を有する先験的何も間違っàあります。私が覚えているようたとえば、あなたは、そのコンテンツに対する問合せと完全PostgreSQLのXML値を持つことができます1
DELIMITER //

DROP PROCEDURE IF EXISTS prepare;

CREATE PROCEDURE prepare() 
BEGIN

   DROP TABLE IF EXISTS assembly;

   CREATE TABLE assembly 
      (id INT AUTO_INCREMENT KEY,    -- surrogate key because a bike may have several wheels
       part VARCHAR(10) NOT NULL, 
       subpart VARCHAR(10) NOT NULL);

   INSERT INTO assembly(part,subpart) VALUES
      ("bike","wheel"),
      ("bike","wheel"),
      ("bike","frame"),
      ("wheel","spoke"),
      ("wheel","rim"),
      ("wheel","hub"),
      ("frame","rearframe"),
      ("frame","frontframe"),
      ("frontframe","fork"),
      ("frontframe","handles"),
      ("hub","gears"),
      ("hub","axle"),
      ("axle","bolt"),
      ("axle","nut");
END;

DROP PROCEDURE IF EXISTS compute_transitive_closure;

CREATE PROCEDURE compute_transitive_closure()
BEGIN

   DROP TABLE IF EXISTS pieces;

   CREATE TABLE pieces
      (id      INT AUTO_INCREMENT KEY,
       part    VARCHAR(10) NOT NULL,
       subpart VARCHAR(10) NOT NULL,
       path    VARCHAR(500) NOT NULl DEFAULT "",
       depth   INT NOT NULL DEFAULT 0);

   INSERT INTO pieces(part,subpart,path,depth) VALUES
      ("ROOT","bike","/bike",0);

   SET @depth=0;

   l: LOOP
      INSERT INTO pieces(part,subpart,path,depth)
      SELECT
         p.subpart,
         a.subpart,
         CONCAT(p.path,'/',a.subpart),
         @depth+1
      FROM
         pieces   p,
         assembly a
      WHERE
         p.depth = @depth AND p.subpart = a.part;

      IF ROW_COUNT() <= 0 THEN
         LEAVE l;
      ELSE
         SELECT * FROM pieces;
      END IF;

      SET @depth=@depth+1;
   END LOOP;

END; //

DELIMITER ;

ファイルに上記を入れてSQL.txt、データベースに、そして、とtestme

MariaDB [testme]> source SQL.txt;
MariaDB [testme]> CALL prepare;
MariaDB [testme]> CALL compute_transitive_closure;

その後、ループを通る4回の継代後、次のようになります。

+----+------------+------------+--------------------------------+-------+
| id | part       | subpart    | path                           | depth |
+----+------------+------------+--------------------------------+-------+
|  1 | ROOT       | bike       | /bike                          |     0 |
|  2 | bike       | wheel      | /bike/wheel                    |     1 |
|  3 | bike       | wheel      | /bike/wheel                    |     1 |
|  4 | bike       | frame      | /bike/frame                    |     1 |
|  5 | wheel      | spoke      | /bike/wheel/spoke              |     2 |
|  6 | wheel      | spoke      | /bike/wheel/spoke              |     2 |
|  7 | wheel      | rim        | /bike/wheel/rim                |     2 |
|  8 | wheel      | rim        | /bike/wheel/rim                |     2 |
|  9 | wheel      | hub        | /bike/wheel/hub                |     2 |
| 10 | wheel      | hub        | /bike/wheel/hub                |     2 |
| 11 | frame      | rearframe  | /bike/frame/rearframe          |     2 |
| 12 | frame      | frontframe | /bike/frame/frontframe         |     2 |
| 20 | frontframe | fork       | /bike/frame/frontframe/fork    |     3 |
| 21 | frontframe | handles    | /bike/frame/frontframe/handles |     3 |
| 22 | hub        | gears      | /bike/wheel/hub/gears          |     3 |
| 23 | hub        | gears      | /bike/wheel/hub/gears          |     3 |
| 24 | hub        | axle       | /bike/wheel/hub/axle           |     3 |
| 25 | hub        | axle       | /bike/wheel/hub/axle           |     3 |
| 27 | axle       | bolt       | /bike/wheel/hub/axle/bolt      |     4 |
| 28 | axle       | nut        | /bike/wheel/hub/axle/nut       |     4 |
| 29 | axle       | bolt       | /bike/wheel/hub/axle/bolt      |     4 |
| 30 | axle       | nut        | /bike/wheel/hub/axle/nut       |     4 |
+----+------------+------------+--------------------------------+-------+

1:これは私が掘る製:「実務家のためのリレーショナル理論の深さのデータベース」をすることにより、オライリー2005、クリス日、リレーショナルモデルに優れた導入を。30ページ、日付は「値として設定し、」みなし(しかし、「マルチセット」を考慮しません)。

第二に(と関係なく、あなたが私の最初の引数を考えるかもしれないものの)、事実であるそのセットのような {P2,P4,P5}これ以上およびDBMSによって劣らず分解の文字列よりもされません。文字列のように、セットは、いくつかの内部構造を持っています。文字列と同じように、しかし、それは特定の目的のためにその構造を無視すると便利です。あまりにも、その後、セットでなければなりません - 文字列がアトミックである場合に、ある - つまり、文字列は1NFの要件と互換性がある場合。私はここで取得しています本当のポイントは、アトミックの概念が無い絶対的な意味を持っているということです。それはちょうど私たちがデータで何をしたいかに依存します。時には我々は、単一のものとしてパーツ番号のセット全体に対処したい、そして時には我々は、そのセット内の個々の部品番号に対処したい - しかし、我々は、下位の詳細レベル(抽象化の低いレベル)に下降しています。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=20506&siteId=1