查询hierarchyID表的父项和前两个子项

时间:2015-07-05 16:22:59

标签: sql select hierarchyid

我试图从使用HiearchyID的单个表中获取Parent及其左上角和右上角的子项。几个星期以来我一直在喋喋不休,并希望得到任何帮助。

这是一张存储'事实的单一表格。对于一个学校辩论小组来说,每个事实都有儿童事实,这些事实可以是“和”。或者反对'父母的事实。我希望得到父母和最近的' for'最近的反对'摘要页面的事实。相反,我会与这些组合中的每个组合进行交叉联合。

这是我的表:

{ d '2015-07-05' }

这是我当前的疑问:

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

注意:

  1. TOP(1)如果只有一个父母会工作,但我真正的桌子有很多顶级父母。
  2. 根事实始终为2级,前两个树级别基本上只是占位符。
  3. 我在SQL Server 2014上使用T-SQL。
  4. 真的很感激任何提示或解决方案!

1 个答案:

答案 0 :(得分:0)

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

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标志。