Joe Celko の本(38 ページ) に従って、Path Enumeration モデルを実装しようとしています。私のテーブル (および連続する整数のみを含むサポート テーブル) の関連する属性は次のようになります。
Contribution
------------
ContributionID
PathString
_IntegerSeries
--------------
IntegerID
_IntegerSeries には 1 から n までの整数が含まれており、n は必要以上に大きくなっています。寄稿には次の 3 つのレコードが含まれます。
1 1
2 12
3 123
... そして、Joe のクエリの修正版を使用します。
SELECT SUBSTRING( c1.PathString
FROM (s1.IntegerID * CHAR_LENGTH(c1.ContributionID))
FOR CHAR_LENGTH(c1.ContributionID)) AS ContID
FROM
Contribution c1, _IntegerSeries s1
WHERE
c1.ContributionID = 3
AND s1.IntegerID <= CHAR_LENGTH(c1.PathString)/CHAR_LENGTH(c1.ContributionID);
... 階層内の ContributionID 3 のすべての上司を含む結果セットを正常に返します。さて、この例では、PathString 列にはプレーンな整数値が保持されており、ContributionID 10 に達すると明らかに問題が発生します。そのため、PathString 列を変更してセパレーターを含めます。
1 1.
2 1.2.
3 1.2.3.
さて...この本は、PathStringが区切り文字を使用するときに上位を取得する例を示していません...したがって、後でそれを理解する必要があります。しかし、それは PathString を分割する方法の例を示しています (これは、優れた検索を行うのに役立つと思います)。これを行うサンプル コードの MySQL バージョンは次のとおりです。
SELECT SUBSTRING( '.' || c1.PathString || '.'
FROM s1.IntegerID + 1
FOR LOCATE('.', '.' || c1.PathString || '.', s1.IntegerID + 1) - s1.IntegerID - 1) AS Node
FROM _IntegerSeries s1, Contribution c1
WHERE
SUBSTRING('.' || c1.PathString || '.' FROM s1.IntegerID FOR 1) = '.'
AND IntegerID < CHAR_LENGTH('.' || c1.PathString || '.');
...しかし、このコードは空の結果セットを返します。私は何か間違ったことをしていますが、何がわかりません。Joe にメールで迷惑をかける前に、これを stackoverflow コミュニティに公開することにしました。誰にも考えはありますか?
アップデート
Quassnoi のクエリ... テスト後に少し変更されましたが、機能的には元のクエリとまったく同じです。非常に素晴らしい。今まで使っていたものよりきれいになりました。本当にありがとう。
SET @contributionID = 3;
SELECT ca.*
FROM
Contribution c INNER JOIN _IntegerSeries s
ON s.IntegerID < @contributionID AND SUBSTRING_INDEX(c.PathString, '.', s.IntegerID) <> SUBSTRING_INDEX(c.PathString, '.', s.IntegerID + 1)
INNER JOIN Contribution ca
ON ca.PathString = CONCAT(SUBSTRING_INDEX(c.PathString, '.', s.IntegerID), '.')
WHERE c.ContributionID = @contributionID;