我必须创建层次结构并将其应用于客户,而我无法控制客户表或其数据库。
为此,我正在创建一个单独的数据库,其中将包含虚拟客户和映射表。
还有其他一些过程可以使用此脚本的结果,并将其从不受控制的Db应用于客户。
VirtualCustomer表-我可以控制此表的设计。
这些“客户”代表必须应用的层次结构。
VirCustID | ParentVirCustID | Name
2001 | NULL | Vehicle
2002 | 2001 | Car
2003 | NULL | Tech
2004 | 2003 | Comms
HierarchyAssignment Table -我可以控制此表的设计
使用此表作为将客户加入虚拟客户的机制。然后,虚拟客户将拥有其余的层次结构。
重要:我将CustID映射到层次结构的最低级别,因此需要从下往上递归。
CustID是该数据库之外的客户的ID,我无法控制。我也不需要加入该表。
CustID | VirCustID
1001 | 2001
1002 | 2001
1003 | 2003
我正在尝试获得结果:
CustID | L1ID | L1Name | L2ID | L2Name
1001 | 2001 | Vehicle | 2002 | Car
1002 | 2001 | Vehicle | 2002 | Car
1003 | 2003 | Tech | 2004 | Comms
1004 | NULL | NULL | NULL | NULL
目前我只对2个级别感兴趣,尽管有可能需要增加它,因此使用了一个映射表。我需要能够支持L n ID和名称。
我认为我需要CTE递归并且可能需要重做,并且尝试了一些我从其他Q / A中获得的东西,尽管还没有成功。
这是我正在玩的脚本之一。我只是不知道从哪里开始,将不胜感激地收到任何指针。
WITH cp AS
(
SELECT p.VirCustID, p.parentVirCustID, 0 as [level]
FROM VirtualCustomer as p
WHERE p.parentVirCustIDis null
UNION ALL
SELECT p2.VirCustID, p2.parentVirtualId, c.[level]+1
FROM VirtualCustomer as p2
JOIN cp as c on p2.parentVirCustID= c.VirtCustID
)
select * from cp
答案 0 :(得分:0)
您可以通过执行简单的连接(假设您在执行此代码的任何地方都可以访问所有相关表),在单个查询中完成所需的结果。
这是具有所需输出的数据库小提琴: https://www.db-fiddle.com/f/hsdHCRJNcsg7ZpXbgJ7mbS/0
层次结构链接有点违反直觉,因为您是将父级“反向”链接到子级。
以下是查询:
SELECT cust.custid
,sq_levelone.vircustid AS l1id
,sq_levelone.name AS l1name
,sq_leveltwo.vircustid AS l2id
,sq_leveltwo.name AS l2name
FROM sq_sourcesystemcustids cust
LEFT JOIN sq_hierarchyassignment hier ON cust.custid = hier.custid
LEFT JOIN sq_virtualcustomer sq_levelone ON (hier.vircustid = sq_levelone.vircustid)
LEFT JOIN sq_virtualcustomer sq_leveltwo ON (sq_levelone.vircustid = sq_leveltwo.parentvircustid)
答案 1 :(得分:0)
扩展Brent的答案,因为您希望在单个查询中执行此操作,所以您可能最终会使用他的方法,但将其推断出所需的级别。
SELECT DISTINCT c.custid,
Levelone.vircustid AS l1id,
Levelone.NAME AS l1name,
Leveltwo.vircustid AS l2id,
Leveltwo.NAME AS l2name,
Levelthree.vircustid AS l3id,
Levelthree.NAME AS l3name,
Levelfour.vircustid AS l4id,
Levelfour.NAME AS l4name,
Levelfive.vircustid AS l5id,
Levelfive.NAME AS l5name,
Levelsix.vircustid AS l6id,
Levelsix.NAME AS l6name,
Levelseven.vircustid AS l7id,
Levelseven.NAME AS l7name,
Leveleight.vircustid AS l8id,
Leveleight.NAME AS l8name,
Levelnine.vircustid AS l9id,
Levelnine.NAME AS l9name,
Levelten.vircustid AS l10id,
Levelten.NAME AS l10name
FROM sourcecustomerids c
LEFT JOIN hierarchyassignment h
ON c.custid = h.custid
LEFT JOIN virtualcustomer Levelone
ON ( h.vircustid = Levelone.vircustid )
LEFT JOIN virtualcustomer Leveltwo
ON ( Levelone.vircustid = Leveltwo.parentvircustid )
LEFT JOIN virtualcustomer Levelthree
ON ( Leveltwo.vircustid = Levelthree.parentvircustid )
LEFT JOIN virtualcustomer Levelfour
ON ( Levelthree.vircustid = Levelfour.parentvircustid )
LEFT JOIN virtualcustomer Levelfive
ON ( Levelfour.vircustid = Levelfive.parentvircustid )
LEFT JOIN virtualcustomer Levelsix
ON ( Levelfive.vircustid = Levelsix.parentvircustid )
LEFT JOIN virtualcustomer Levelseven
ON ( Levelsix.vircustid = Levelseven.parentvircustid )
LEFT JOIN virtualcustomer Leveleight
ON ( Levelseven.vircustid = Leveleight.parentvircustid )
LEFT JOIN virtualcustomer Levelnine
ON ( Leveleight.vircustid = Levelnine.parentvircustid )
LEFT JOIN virtualcustomer Levelten
ON ( Levelnine.vircustid = Levelten.parentvircustid )
如果您需要添加或删除额外的图层,如何将它们串联在一起应该很明显。如果使用键盘进行生活,D / p大约需要5-10秒才能添加/删除
如果您愿意使用存储过程方法,则可以根据数据动态创建正确数量的级别,但是我认为在单个查询中不容易做到这一点。如果您对程序选项感兴趣,我可能会稍作尝试。
HTH
答案 2 :(得分:0)
我正在提交一个替代答案,因为将原始答案保留在网上仍然很有用(如果您选择按照Combee的说明进行操作)。此答案同时使用了递归(您的初始查询,已修改)和数据透视。
以下代码将允许您按列构建层次结构,但有一些注意事项。 如果希望扩展层数,则仍然需要更改代码。这样做的原因是SQL Server需要列定义(如果我们不编写动态SQL的话)。此外,名称不会在结果中传播。您可以使用函数或将其作为select语句的一部分来获取它们。
要将新级别添加到层次结构中(已包含10个),您将添加一个附加列(即sq_consolidated数组和sq_merge数组中的[11]或[n],将max([n])作为LnID添加到sq_final。
此答案还取决于您在层次结构的最低级别上进行映射(这是要求的一部分)。
WITH
sq_hierarchylevels AS
(SELECT vircustid
,parentvircustid
,name
,1 AS hierlevel
,[name] AS constname
FROM virtualcustomer
WHERE parentvircustid IS NULL
UNION ALL
SELECT i.vircustid
,i.parentvircustid
,i.name
,hierlevel + 1
,hier.constname
FROM virtualcustomer i
INNER JOIN sq_hierarchylevels hier ON hier.vircustid = i.parentvircustid),
sq_consolidated AS
(SELECT *
FROM sq_hierarchylevels hier
PIVOT (max( vircustid )
FOR hierlevel
IN( [1],[2],[3],[4],[5],[6],[7],[8],[9],[10] )) AS piv
WHERE parentvircustid IS NOT NULL),
sq_merge AS
(SELECT orig.vircustid
,orig.parentvircustid
,orig.[name]
,vircustid AS l1id
,orig.[name] AS l1name
,[2],[3],[4],[5],[6],[7],[8],[9],[10]
FROM virtualcustomer orig
LEFT JOIN sq_consolidated fills ON (orig.name = fills.constname)
WHERE orig.parentvircustid IS NULL),
sq_final AS
(SELECT vircustid
,[name]
,max( l1id ) AS l1id
,max( [2] ) AS l2id
,max( [3] ) AS l3id
,max( [4] ) AS l4id
,max( [5] ) AS l5id
,max( [6] ) AS l6id
,max( [7] ) AS l7id
,max( [8] ) AS l8id
,max( [9] ) AS l9id
,max( [10] ) AS l10id
FROM sq_merge
GROUP BY vircustid, name)
SELECT *
FROM sq_final
ORDER BY vircustid