查询 parents 和 hierarchyID table 的前两个 children

Query for parents and top two children of a hierarchyID table

我正在尝试从使用 HiearchyID 的单个 table 中获取 Parent 及其左上角和右上角 children。几个星期以来我一直在努力解决这个问题,希望得到任何帮助。

这是一个为学校辩论队存储 'facts' 的单个 table,每个事实都有 child 个可以是 'for' 或 'against' 的事实parent 事实。我想获取摘要页面的 parent 和最近的 'for' 以及最近的 'against' 事实。相反,我得到的是 cross-union 每个组合。

这是我的 table:

factID (key)    nodeID (hierarchyID)    nodeLevel(computed column) text                        side(1=for, 2=against)  timestamp
=======         ======                   =========                 ====                        =====                     =========
1              /1/2/                     2                         "Kirk rules"                1                         08:00
3              /1/2/1/                   3                         "Great actor!"              1                         08:01
5              /1/2/2/                   3                         "Picard is better."         2                         08:02
7              /1/2/3/                   3                         "best captain ever"         1                         08:03
32             /1/2/4/                   3                         "hate his over-acting"      2                         08:04
43             /1/2/5/                   3                         "PriceLine is great."       1                         08:05
44             /1/2/6/                   3                         "Spock was better too."     2                         08:06

这是我当前的查询:

SELECT P.text AS parentText, P.timeStamp AS parentTimeStamp,  
           L.text AS leftText,  MAX(L.timeStamp) AS leftTimeStamp, 
           R.text AS rightText, MAX(R.timeStamp) AS rightTimeStamp   

FROM app.Facts AS P 
    LEFT OUTER JOIN app.Facts AS L 
            ON (P.nodeID = (L.nodeID).GetAncestor(1))  AND (L.sideID = 1 OR L.sideID IS NULL)

    LEFT OUTER JOIN app.Facts AS R
        ON (P.nodeID = (R.nodeID).GetAncestor(1))  AND (R.sideID = 2 OR R.sideID IS NULL)

WHERE (P.text IS NOT NULL) AND (P.nodeLevel = 2)     

GROUP BY P.text, P.timeStamp, L.text, L.timeStamp, R.text, R.timeStamp
HAVING L.timeStamp = MAX(L.timeStamp) AND R.timeStamp = MAX(R.timeStamp)
ORDER BY P.timeStamp DESC, L.timeStamp DESC, R.timeStamp DESC

这是我想要得到的:

parentText      parentTimeStamp leftText                 leftTimeStamp  rightText              rightTimeStamp
==========      =============== =====================   =============   =========               ==============
"Kirk rules"    08:00           "PriceLine is great."   08:05          "Spock was better too."  08:06
...
"top fact xx"   11:00           'for' fact xx           11:01          'against' fact xx        11:01

这是我得到的:

parentText  parentTimeStamp leftText                leftTimeStamp   rightText                rightTimeStamp
==========  =============== =====================   =============   =========                ==============
"Kirk rules"    08:00       "PriceLine is great."   08:05           "Spock was better too."   08:06
"Kirk rules"    08:00       "PriceLine is great."   08:05           "hate his over-acting"    08:04
"Kirk rules"    08:00       "PriceLine is great."   08:05           "Picard is better."       08:02
"Kirk rules"    08:00       "best captain ever"     08:03           "Spock was better too."   08:06
"Kirk rules"    08:00       "best captain ever"     08:03           "hate his over-acting"    08:04
"Kirk rules"    08:00       "best captain ever"     08:03           "Picard is better."       08:02
"Kirk rules"    08:00       "Great actor!"          08:01           "Spock was better too."   08:06
"Kirk rules"    08:00       "Great actor!"          08:01           "hate his over-acting"    08:04
"Kirk rules"    08:00       "Great actor!"          08:01           "Picard is better."       08:02
...
same thing with rest of the top level facts.

备注:

    如果只有一个 parent,
  1. TOP(1) 会起作用,但我的真实 table 有许多顶级 parent。
  2. 根事实总是第 2 级,最上面的两个树级基本上只是占位符。
  3. 我在 SQL Server 2014 上使用 T-SQL。

非常感谢任何提示或解决方案!

我通过添加两列找到了解决方法:

isLatestForArg     BIT  NOT NULL,
isLatestAgainstArg BIT  NOT NULL

然后将我的查询更改为:

SELECT P.text AS parentText, P.timeStamp AS parentTimeStamp,  
       L.text AS leftText,  MAX(L.timeStamp) AS leftTimeStamp, 
       R.text AS rightText, MAX(R.timeStamp) AS rightTimeStamp   

FROM app.Facts AS P 
LEFT OUTER JOIN app.Facts AS L 
        ON (P.nodeID = (L.nodeID).GetAncestor(1))  AND ((L.sideID IS NULL) OR (L.isLatestForArg = 1))

LEFT OUTER JOIN app.Facts AS R
    ON (P.nodeID = (R.nodeID).GetAncestor(1))  AND ((R.sideID IS NULL) OR (R.isLatestAgainstArg = 1))

显然不理想,因为现在每个 INSERT 都需要更新 isLatestFor/Against 标志。