0

我正在尝试从使用 HiearchyID 的单个表中获取父级及其左上角和右上角的子级。几周来一直在努力,希望能得到任何帮助。

这是一个为学校辩论队存储“事实”的表,每个事实都有子事实,可以“支持”或“反对”父事实。我想获取摘要页面的父项以及最近的“支持”和最近的“反对”事实。相反,我得到了一个与这些组合的交叉联合。

这是我的桌子:

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.

笔记:

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

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

4

1 回答 1

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

于 2015-07-17T13:29:17.743 回答