2

我正在尝试按照 Joe Celko 的(第 38 页)实现路径枚举模型。我的表(以及只包含连续整数的支持表)的相关属性如下所示:

Contribution
------------
ContributionID
PathString

_IntegerSeries
--------------
IntegerID

_IntegerSeries 包含整数 1 到 n,其中 n 比我需要的要大。贡献包含三个记录:

1  1
2  12
3  123

...我使用了乔的查询的修改版本:

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;
4

1 回答 1

2

这是因为||inMySQL是 boolean 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
于 2010-12-30T22:06:57.533 回答