我正在尝试按照Joe Celko的book(第38页)实现Path Enumeration模型。我的表(以及只包含顺序整数的支持表)的相关属性如下所示:
Contribution
------------
ContributionID
PathString
_IntegerSeries
--------------
IntegerID
_IntegerSeries包含整数1到n,其中n比我需要的大。贡献包含三个记录:
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 || '.');
...但此代码返回一个空结果集。我做错了什么,但我不确定是什么。想象一下,在用电子邮件打扰乔之前,我已经把它放到了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;
答案 0 :(得分:2)
这是因为||
中的MySQL
是布尔OR
,而不是字符串连接。
要查找给定Contribution
的所有祖先,请使用:
SELECT ca.*
FROM Contribution с
JOIN IntegerSeries s
ON IntegerID < CHAR_LENGTH(c.path)
AND SUBSTRING_INDEX(c.path, '.', IntegerID) <> SUBSTRING_INDEX(c.path, '.', IntegerID + 1)
JOIN Contribution ca
ON ca.path = CONCAT(SUBSTRING_INDEX(c.path, '.', IntegerID), '.')
WHERE c.ContributionID = 3