我有一张有父子关系的桌子。对于我正在创建的仪表板,我需要创建一个表,以便仪表板 (SAS Viya) 可以使用该表。为此,我需要获取每个公司 id (cid) 的所有父级和子级,包括结构内的级别(例如,如果它是第三级子级)和一个 sort_chain,它是从父级到该级的数字链孩子,因此能够对仪表板中的所有 sort_cid 进行分组/排序。
(名称 sort_ 是因为我稍后将在仪表板中使用这些列来正确显示/排序数据。)
简而言之,我正在尝试从这张表开始:
西德 | parent_cid |
---|---|
a | |
b | a |
c | b |
d | a |
e | |
f | |
g | f |
在 SAS 中使用 PROC SQL 到此表:
西德 | 排序_cid | 排序_链 | 排序_级别 |
---|---|---|---|
a | a | 1.1.1 | 1 |
a | b | 1.2.1 | 2 |
a | c | 1.2.2 | 3 |
a | d | 1.3.1 | 2 |
b | a | 1.1.1 | 1 |
b | b | 1.2.1 | 2 |
b | c | 1.2.2 | 3 |
c | a | 1.1.1 | 1 |
c | b | 1.2.1 | 2 |
c | c | 1.2.2 | 3 |
d | a | 1.1.1 | 1 |
d | d | 1.3.1 | 2 |
e | e | 2.1.1 | 1 |
f | f | 3.1.1 | 1 |
f | g | 3.2.1 | 2 |
g | f | 3.1.1 | 1 |
g | g | 3.2.1 | 2 |
我怎样才能实现这个目标?
我尝试过的:
第一步是将所有缺失的parent_cid设置为自身(我们称之为table1):
西德 | parent_cid |
---|---|
a | a |
b | a |
c | b |
d | a |
e | e |
f | f |
g | f |
然后我尝试自连接此表以获取所有已知的女儿,但随后您会得到一个额外的列,而不是额外的行:
SELECT
a.cid, a.parent_cid, b.cid AS sort_chain
FROM
table1 a
INNER JOIN
table1 b
ON
b.parent_company_id = a.company_id;
对于自加入以获取所有已知父母也是如此。
我也尝试了交叉连接,但随后表得到了所有内容x所有内容,这没有意义。
简而言之:我觉得我的思考方向是正确的,但是遗漏了一些东西或者搞砸了一些东西。希望有人能给我提供示例代码或为我指出正确的方向。谢谢!
使用 HASH() 查找每个观察的深度/级别和顶部节点。
data want;
* Load the cid->parent_cid mapping into a hash ;
if _n_=1 then do;
declare hash h(dataset:'have');
h.definekey('cid');
h.definedata('parent_cid');
h.definedone();
end;
* Load next CID value ;
set have ;
* Find their top ancestor and how deep they are ;
do depth=1 by 1 until(h.find());
top=cid;
cid=parent_cid;
end;
* Re-load the same CID value to reset CID and PARENT_CID ;
set have;
run;
要生成计数器,请使用 BY 组处理。 确保为数据的最大深度设置足够的计数器。
proc sort;
by top depth cid ;
run;
* find how many levels will be needed ;
proc sql noprint;
select max(depth) into :md trimmed from want;
quit;
* Use FIRST. processing to get the counters ;
* Concatenate to make index string ;
data numbered;
set want;
by top depth cid;
array c[&md] ;
c[depth]+1;
if first.depth then do;
do j=depth+1 to &md;
c[j]=1;
end;
end;
drop j ;
sort_chain=catx('.',of c[*]);
run;