我有一个表,其中包含与非常大的文档有关的信息。该表如下所示:
this.configService.getConfig()
.subscribe(
(data: Config) => this.config = { ...data },
error => this.error = error,
() => this.preFetchData()
);
}
preFetchData() {
this.i = 0;
for (const value of this.bases) {
if (this.config) {
this.i++;
this.configService.tableData[this.i - 1].buy = this.config.rates[value.curr] - (this.config.rates[value.curr] / 100 * 5);
this.configService.tableData[this.i - 1].sell = this.config.rates[value.curr] + (this.config.rates[value.curr] / 100 * 5);
console.log(this.currency, this.date, this.configService.tableData[this.i - 1].buy);
}
}
}
结果JSON应该看起来像(为了清楚起见,省略了ID | Title | Parent_ID | <other columns>
--------+---------------+---------------+-------------------
0 | Root | null | ...
1 | Introduction | 0 | ...
2 | Glossary | 1 | ...
3 | Audience | 1 | ...
4 | "A" | 2 | ...
5 | "B" | 2 | ...
6 | "C" | 2 | ...
部分):
<other columns>
我确实有一个简单的(递归)过程可以处理此问题,但希望使用DBMS的JSON功能(可能使用CTE?)有更简单的方法。
答案 0 :(得分:1)
是否知道父母/子女关系的最大深度?
然后,您可以像下面的示例那样将其拉开:
对 db <>小提琴here
的测试测试数据:
CREATE TABLE documentdetails
(
ID INT PRIMARY KEY NOT NULL,
Title VARCHAR(30) NOT NULL,
Parent_ID INT,
FOREIGN KEY (Parent_ID) REFERENCES documentdetails (ID)
);
INSERT INTO documentdetails (ID, Title, Parent_ID) VALUES
(1, 'Root', null), (2, 'Introduction', 1), (3, 'Glossary', 1),
(4, 'Audience', 1), (5, 'A', 2), (6,'B', 2), (7, 'C', 2),
(8, 'Foo', null), (9, 'Bar Intro', 8), (10, 'Glossy stuff', 8), (11, 'What The Fook', 8),
(12, 'Yo', 9), (13, 'Ai', 10), (14, 'Potato', 11);
查询:
SELECT
root.ID,
root.Title,
(
SELECT lvl0.ID, lvl0.Title, 0 as Depth,
(
SELECT lvl1.ID, lvl1.Title, 1 as Depth,
(
SELECT lvl2.ID, lvl2.Title, 2 as Depth,
(
SELECT lvl3.ID, lvl3.Title, 3 as Depth
FROM documentdetails lvl3
WHERE lvl3.Parent_ID = lvl2.ID
FOR JSON PATH
) AS Contents
FROM documentdetails lvl2
WHERE lvl2.Parent_ID = lvl1.ID
FOR JSON PATH
) AS Contents
FROM documentdetails lvl1
WHERE lvl1.Parent_ID = lvl0.ID
FOR JSON PATH
) AS Contents
FROM documentdetails lvl0
WHERE lvl0.ID = root.ID
FOR JSON PATH
) AS Contents
FROM documentdetails root
WHERE root.Parent_ID IS NULL;
结果:
ID Title Contents
-- ----- --------
1 Root [{"ID":1,"Title":"Root","Depth":0,"Contents":[{"ID":2,"Title":"Introduction","Depth":1,"Contents":[{"ID":5,"Title":"A","Depth":2},{"ID":6,"Title":"B","Depth":2},{"ID":7,"Title":"C","Depth":2}]},{"ID":3,"Title":"Glossary","Depth":1},{"ID":4,"Title":"Audience","Depth":1}]}]
8 Foo [{"ID":8,"Title":"Foo","Depth":0,"Contents":[{"ID":9,"Title":"Bar Intro","Depth":1,"Contents":[{"ID":12,"Title":"Yo","Depth":2}]},{"ID":10,"Title":"Glossy stuff","Depth":1,"Contents":[{"ID":13,"Title":"Ai","Depth":2}]},{"ID":11,"Title":"What The Fook","Depth":1,"Contents":[{"ID":14,"Title":"Potato","Depth":2}]}]}]
如果您不知道表格中的最大深度?
这是使用递归CTE来获得有关此想法的SQL。
WITH RCTE AS
(
SELECT ID as rootID, 0 as lvl, ID, Parent_ID
FROM documentdetails
WHERE Parent_ID IS NULL
UNION ALL
SELECT r.rootID, lvl + 1, t.ID, t.Parent_ID
FROM RCTE r
JOIN documentdetails t ON t.Parent_ID = r.ID
)
SELECT rootID, MAX(lvl) as Depth, COUNT(*) as Nodes
FROM RCTE
GROUP BY rootID
ORDER BY MAX(lvl) DESC, COUNT(*) DESC;
或者相反,从孩子们那里播种。
(如果ID是PRIMARY KEY,则由于ID上的JOIN可能会更快)
WITH RCTE AS
(
SELECT ID as baseID, 0 as lvl, ID, Parent_ID
FROM documentdetails
WHERE Parent_ID IS NOT NULL
UNION ALL
SELECT r.baseID, lvl + 1, t.ID, t.Parent_ID
FROM RCTE r
JOIN documentdetails t ON t.ID = r.Parent_ID
)
SELECT ID as rootID, MAX(lvl) as Depth
FROM RCTE
WHERE Parent_ID IS NULL
GROUP BY ID
ORDER BY MAX(lvl) DESC, COUNT(*) DESC;