父子关系表

问题描述 投票:1回答:2

语境:

  • 查询来自外部系统的事务表,以在具有两个主要列的本地系统上创建元素:
  • 尚未保留在本地数据库中的子项
  • 可能的多个父母分号分开(可以在本地保存或尚未创建)

我在排序看起来像这样的表时遇到问题:

Child    Parents
A        B;C
B        C;E
C        F;X

我想要完成的是确保始终在子项之前创建父:

Child    Parents
C        F;X
B        C;E
A        B;C

此示例中的F,X和E表示已存在于本地数据库中的元素,这些元素可能位于我的查询中

我花了一些时间思考这个问题,似乎它与树木/图表有关,我几乎不知道......

知道我们在这里处理什么样的排序以及可能的java或SQL实现?

编辑:

  • 每个子元素都是数据库中尚未保留的元素
  • 一个孩子可以有一个父母已经坚持的名单(如F,X和E)或父母我仍然需要坚持(在这种情况下他们需要先于孩子)或两者兼而有(比如B与C; E父母) E已经存在并且C进入此交易并且必须在B)之前
  • 无法更改数据库,但可以在java中自由重新排序

提前致谢

部分解决方案我已经改编了Joshua的解决方案,它似乎以这种方式工作:

(基本上使用like声明,因为我们可以有类似AA的东西; BB; CC作为父亲)

SELECT DISTINCT
s1.child,
s1.parents,
    CASE
        WHEN s2.parents IS NULL THEN 0
        WHEN s2.parents LIKE '%' + s1.child + '%' THEN 1
        ELSE 3
    END
AS x
FROM
sample s1
LEFT JOIN sample s2 ON s2.parents LIKE '%' + s1.child + '%'
WHERE
s1.treateddate IS NULL
ORDER BY
CASE
    WHEN s2.parents IS NULL THEN 0
    WHEN s2.parents LIKE '%' + s1.child + '%' THEN 1
    ELSE 3
END
DESC

此解决方案不会同时考虑父母的孩子!

解决方案Java我在Java中找到了重新排序数据集的解决方案,这只是伪代码,因为我使用的是专有库...

private void sortByParentFirst(rows) {
for (int i = 0; i < rows.size(); i++) {
    for (int j = 0; j < rows.size(); j++) {
         boolean match = false;
         //parents comma seperated at j contain child i
         if (Parents[j].contains(Child[i]) ) {
             match = true;
         }
         //this means we found an occurrence of the child i at a previous position j
         if (match && j < i) {
            //swap rows i & j
            swap(i,j);
            break;
         }
     }
}
}
java sql sql-server tree
2个回答
0
投票

表格示例包含您的数据

select * from sample

chid parents
---- ----------
A    B;C
B    C;E
C    F;X

select * from sample

drop table #sample
drop table #sample2

select * into #sample from sample
select * into #sample2 from sample where 1=2

alter table #sample2 add counter int

declare @count int
select @count = count(1) from #sample

declare @child char(1)
declare @counter int = 1

while(@count > 0)
begin
    select @child = t1.chid
    from #sample t1
    inner join #sample t2 on CHARINDEX(t1.chid,t2.parents) = 0
    group by t1.chid
    having count( t1.chid) = 1

    insert into #sample2
    select *,@counter from #sample where chid = @child

    delete from #sample where chid = @child

    select @count = count(1) from #sample
    set @counter = @counter + 1
end

select chid, parents from #sample2 order by counter

0
投票
select distinct s1.*  ,
case when s2.parents is null and s3.parents is null then 0 
 when s1.child = left(s2.parents,1) and s3.parents is null  then 1
 when s1.child = right(s3.parents,1) and s2.parents is null  then 2
else 3 end as x
from sample s1
left join sample s2 on s1.child = left(s2.parents,1) 
left join sample s3 on s1.child = right(s3.parents,1)
order by 
case when s2.parents is null and s3.parents is null then 0 
 when s1.child = left(s2.parents,1) and s3.parents is null  then 1
 when s1.child = right(s3.parents,1) and s2.parents is null  then 2
else 3 end desc

SQL Fiddle Example

将表连接回自己两次寻找与父母的匹配。如果实际日期不仅仅是一个字符,那么您可以使用CHARINDEX来定位分隔符,并根据返回的起始位置的位置左右定位每个分隔符。

© www.soinside.com 2019 - 2024. All rights reserved.