【问题标题】:Join within same table to retrieve hierarchy (Parent-Child Hierarchy)在同一个表中加入以检索层次结构(父子层次结构)
【发布时间】:2019-09-24 10:10:02
【问题描述】:

我有两张桌子 - MasterChild。子表包含存储在主表中的 MainId 的分层数据。

Master.Name 是唯一的

Master.MainId = Child.ChildId

Child.ParentId = Child.ChildId

我必须从 Child 表中检索 Master.RelDate 和 Master.Name 的所有数据。我认为这是一个直截了当的查询,但不知何故无法提取所需的输出。无论我如何编写查询,我最终都会得到一个子表记录。

是表结构还是我的查询?

注意:ParentIds 和 ChildIds 中没有一个是按顺序排列的。这些数据来自另一个系统,为了简单起见,我只是把这些值放在了上面。

IF OBJECT_ID('tempdb..#Master') IS NOT NULL BEGIN DROP TABLE #Master END
GO
IF OBJECT_ID('tempdb..#Child') IS NOT NULL BEGIN DROP TABLE #Child END
GO
CREATE TABLE #Master
(
    Id BIGINT IDENTITY(1,1),
    RelDate DATE NOT NULL,
    MainId BIGINT NOT NULL,
    Name VARCHAR(512) NOT NULL
)
GO
CREATE TABLE #Child
(
    Id BIGINT IDENTITY(1,1),
    RelDate DATE NOT NULL,
    ChildId BIGINT NOT NULL,
    ParentId BIGINT NULL,
    Label VARCHAR(20) NULL,
    Value VARCHAR(1024) NULL
)
GO

INSERT INTO #Master(RelDate,MainId,Name) VALUES ('2019-01-01',1,'Name1')
INSERT INTO #Master(RelDate,MainId,Name) VALUES ('2019-01-01',11,'Name11')
GO
INSERT INTO #Child(RelDate,ChildId,ParentId,Label,Value) VALUES
('2019-01-01',1,2,'Level10',NULL)
,('2019-01-01',2,3,'Level09',NULL)
,('2019-01-01',3,4,'Level08',NULL)
,('2019-01-01',4,5,'Level07',NULL)
,('2019-01-01',5,6,'Level06','This is level 6')
,('2019-01-01',6,7,'Level05',NULL)
,('2019-01-01',7,8,'Level04',NULL)
,('2019-01-01',8,9,'Level03','This is level 3')
,('2019-01-01',9,10,'Level02',NULL)
,('2019-01-01',10,11,'Level01',NULL) -- Always same
,('2019-01-01',11,NULL,'Root',NULL) -- Always same

INSERT INTO #Child(RelDate,ChildId,ParentId,Label,Value) VALUES
('2019-01-01',11,12,'Level10',NULL)
,('2019-01-01',12,13,'Level09',NULL)
,('2019-01-01',13,14,'Level08',NULL)
,('2019-01-01',14,15,'Level07',NULL)
,('2019-01-01',15,16,'Level06','This is level 6')
,('2019-01-01',16,17,'Level05',NULL)
,('2019-01-01',17,18,'Level04',NULL)
,('2019-01-01',18,19,'Level03','This is level 3')
,('2019-01-01',19,10,'Level02',NULL)
,('2019-01-01',10,11,'Level01',NULL) -- Always same
,('2019-01-01',11,NULL,'Root',NULL) -- Always same
GO

SELECT * FROM #Master
SELECT * FROM #Child

RelDate = 2019-01-01 和 Name = Name1 的所需输出

SELECT chld.*
FROM #Master mst (NOLOCK)
    INNER JOIN #Child chld (NOLOCK) ON (mst.MainId = chld.ChildId)
    LEFT JOIN #Child chld1 (NOLOCK) ON (chld.ParentId = chld.ChildId)
WHERE mst.RelDate = '2019-01-01' -- Input 1
AND mst.Name = 'Name1' -- Input 2

子表中的所有数据

Id  RelDate ChildId ParentId    Label   Value
1   2019-01-01  1   2   Level10 NULL
2   2019-01-01  2   3   Level09 NULL
3   2019-01-01  3   4   Level08 NULL
4   2019-01-01  4   5   Level07 NULL
5   2019-01-01  5   6   Level06 This is level 6
6   2019-01-01  6   7   Level05 NULL
7   2019-01-01  7   8   Level04 NULL
8   2019-01-01  8   9   Level03 This is level 3
9   2019-01-01  9   10  Level02 NULL
10  2019-01-01  10  11  Level01 NULL
11  2019-01-01  11  NULL    Root    NULL

提前致谢

【问题讨论】:

  • 分享你想要的输出
  • 问题中包含的输出
  • 为此您需要一个递归 CTE,并删除数据中的循环(10 到 19、19 到 18... 回到 10,然后 10 到 19 再次形成无限循环)。
  • @EzLo 数据就是这样。这些ID来自其他系统,无法控制。你有 CTE 的例子吗?
  • This answer 演示了一种通过跟踪已处理的行来处理数据循环的方法。

标签: sql sql-server database tsql


【解决方案1】:
select c.* from #Child c inner join #Master M
on M.MainId = C.ChildId

Id  RelDate ChildId ParentId    Label   Value
1   2019-01-01  1   2   Level10 NULL
11  2019-01-01  11  NULL    Root    NULL

如果这不是您想要的输出,请提供您想要的输出。

【讨论】:

  • 你错过了输入参数
  • 问题中包含的输出
【解决方案2】:

这表明表格中的数据有点不合逻辑。尤其是“Name11”。我假设每个新行都会从 Childid 列中丢失一个 id。现在我们在第 19 行丢失了“lvl2”。
我试图找出一些解决方案,现在我的位置在这里。
它适用于“Name1”,但“Name11”的结果有点不同。

SELECT   t2.* 
FROM #Master mst 
      join  #Child t1 ON mst.MainId = t1.ChildId
           join  #Child t2 ON t2.parentid >= t1.ChildId  

WHERE mst.RelDate = '2019-01-01' -- Input 1
AND mst.Name = 'Name1'           -- Input 2

order by t2.id 
offset 0 rows 
fetch first 10 rows only

也许对你有一点帮助。我会尝试找到一个棘手的解决方案。

【讨论】:

  • 感谢您的意见。我想我应该提到 ParentId 和 ChildId 上没有一个是按顺序排列的。这些数据来自另一个系统,为了简单起见,我只是把这些值放在了上面。
  • 由于某种原因无法编辑 cmets。 ParentId 和 ChildId 不按顺序排列
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 2020-05-29
  • 1970-01-01
  • 1970-01-01
  • 2022-08-23
相关资源
最近更新 更多