2015-07-05 3 views
0

Я пытаюсь получить родителя, а его верхние левые и верхние правые дети - из одной таблицы, использующей HiearchyID. Я стучал головой об этом несколько недель и был бы признателен за любую помощь.Запрос для родителей и двух верхних дочерних элементов таблицы hierarchyID

Это единый стол, в котором хранятся «факты» для команды школьных дебатов, каждый факт имеет дочерние факты, которые могут быть «за» или «против» родительского факта. Я хотел бы получить родителя и последний «за» и последний «против» факт для сводной страницы. Вместо этого я получаю перекрестный союз с каждой их комбинацией.

Вот мой стол:

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. Я использую T-SQL на SQL Server 2014.

Действительно оценить любые советы или решения!

ответ

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)) 

Очевидно не идеальной, так как теперь каждый ВСТАВИТЬ требует обновления isLatestFor/Против флага.

 Смежные вопросы

  • Нет связанных вопросов^_^