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. 親が 1 つしかない場合は TOP(1) が機能しますが、実際のテーブルには多くの最上位の親があります。
  2. ルート ファクトは常にレベル 2 であり、上位 2 つのツリー レベルは基本的に単なるプレースホルダーです。
  3. SQL Server 2014 で T-SQL を使用しています。

ヒントや解決策を本当にありがとう!

4

1 に答える 1

0

2つの列を追加することで回避策を見つけました:

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 に答える