特定の開始ノードの親ID(pid
)を指定して、バイナリツリー構造(joiningDateによってグループ化された出力)の左ノードと右ノードをカウントする必要があります。
ツリーは次の表に格納されています。
たとえば、pid = 4
を使用すると2 cid
(5および11)が得られ、次にそれらを新しいpid
(5、11)として使用します。 cid
がnullであるか、ツリー全体がトラバースされている場合は、placement = L
およびplacement = R
をすべてカウントします。 「M」のような他の配置は無視されるべきです。
図:
選択した開始ノード4の予想される出力:
+-----------+-------------+-------+
| placement | joiningDate | Total |
+-----------+-------------+-------+
| L | 2015-02-02 | 3 |
| R | 2015-02-02 | 1 |
| L | 2015-08-21 | 4 |
| L | 2015-12-12 | 1 |
+-----------+-------------+-------+
これは、SQL Serverで 再帰的共通テーブル式 を使用して最も簡単に実装できます。
DECLARE @binaryUser AS TABLE
(
id integer NOT NULL,
joiningDate date NOT NULL,
placement char(1) NOT NULL,
pId integer NOT NULL,
cId integer NOT NULL,
referBy integer NOT NULL
);
INSERT @binaryUser
(id, joiningDate, placement, pid, cid, referBy)
VALUES
(4, '20150202', 'L', 4, 5, 4),
(6, '20150202', 'R', 5, 8, 4),
(8, '20150202', 'R', 4, 11, 4),
(9, '20150202', 'L', 5, 10, 4),
(25, '20151212', 'L', 8, 9, 4),
(31, '20150821', 'R', 8, 12, 4),
(33, '20150821', 'R', 12, 13, 4),
(36, '20150821', 'R', 9, 14, 4),
(37, '20150821', 'M', 9, 15, 4),
(38, '20150821', 'L', 10, 16, 4),
(39, '20150821', 'M', 4, 17, 4);
これはスクリプトとして表示されますが、ストアドプロシージャに変換するのは簡単です。基本的な考え方は、ツリーを再帰的に走査し、見つかった行をカウントすることです。
DECLARE @pId integer = 4;
-- Recursive CTE
WITH R AS
(
-- Anchor
SELECT
BU.joiningDate,
BU.cId,
BU.placement
FROM @binaryUser AS BU
WHERE
BU.pId = @pId
AND BU.placement IN ('L', 'R')
UNION ALL
-- Recursive part
SELECT
BU.joiningDate,
BU.cId,
R.placement
FROM R
JOIN @binaryUser AS BU
ON BU.pId = R.cId
WHERE
BU.placement IN ('L', 'R')
)
-- Final groups of nodes found
SELECT
R.placement,
R.joiningDate,
Total = COUNT_BIG(*)
FROM R
GROUP BY
R.placement,
R.joiningDate
OPTION (MAXRECURSION 0);
出力:
╔═══════════╦═════════════╦═══════╗
║ placement ║ joiningDate ║ Total ║
╠═══════════╬═════════════╬═══════╣
║ L ║ 2015-02-02 ║ 3 ║
║ R ║ 2015-02-02 ║ 1 ║
║ L ║ 2015-08-21 ║ 4 ║
║ L ║ 2015-12-12 ║ 1 ║
╚═══════════╩═════════════╩═══════╝