Sql 从多对多联接返回唯一的组合

Sql 从多对多联接返回唯一的组合,sql,sql-server-2008,hierarchy,Sql,Sql Server 2008,Hierarchy,我有一个包含以下数据的层次结构表: SOURCE TARGET Level ID 0 1 1 1 0 2 1 2 2 3 2 3 2 4 2 4 2 5 2 5 1 3 2 6 1 4 2 7 1 5 2

我有一个包含以下数据的层次结构表:

SOURCE  TARGET  Level   ID
0       1       1       1
0       2       1       2
2       3       2       3
2       4       2       4
2       5       2       5
1       3       2       6
1       4       2       7
1       5       2       8
5       3       3       9
5       3       3       10
4       3       3       11
4       3       3       12
3       6       3       13
3       6       3       14
3       6       4       15
3       6       4       16
3       6       4       17
3       6       4       18
源行和目标行是原始数据,用于连接父级和子级。例如,第三行(级别2上的源2、目标3)连接到第二行(级别1上的源0、目标2),因为第一行的源等于第二行的目标
ID列使用ROW_NUMBER函数添加到末尾,用于为每行提供唯一的ID。
如果将源替换为父级,将目标替换为子级,可能更容易理解

为了找到“父对象”,我将表连接到它自己
我希望每个级别上的“源”的每个“实例”都连接到其父级之一。哪一个连接起来并不重要,但都需要连接到不同的父母

最终结果应如下所示:

SOURCE  TARGET  Level   ID   P_ID
0       1       1       1    NULL
0       2       1       2    NULL
2       3       2       3    2
2       4       2       4    2
2       5       2       5    2
1       3       2       6    1
1       4       2       7    1
1       5       2       8    1
5       3       3       9    5
5       3       3       10   8
4       3       3       11   4
4       3       3       12   7
3       6       3       13   3
3       6       3       14   6
3       6       4       15   9
3       6       4       16   10
3       6       4       17   11
3       6       4       18   12
关于如何为此编写一个好的ms sql查询,有什么建议吗?

链接到示例数据和

下面是要使用的查询

;with cte as (
  select *,rn=row_number() over (partition by level, target
                                 order by id),
           lc=count(1) over (partition by level, target)
  from tbl
)

select a.*, b.id as parent_id
from cte a
left join cte b on b.level=a.level-1
               and b.target=a.source
               and b.rn=(a.rn-1)%b.lc+1
order by id
  • 项目在每个级别/目标组合上排序
  • 子对象使用“按顺序”链接到父对象,但是如果子对象多于父对象,则MOD(%)操作符将负责返回到第一个父对象并继续分发

  • 你需要更多的数据,或者当你不可避免地用更多的规则展开时,你得到的任何建议都是不够的。你认为我应该展示一整套例子吗?我有一个小的(完整的)数据集,大约18行。你觉得怎么样?@Gidil,一个18行的数据集会很有帮助。所以,基本上,平衡每个级别的“子级”和早期级别的“父级”,对吗?是的,听起来不错。我还没能把它说得那么好。首先,谢谢你的回答。起初,它看起来会起作用,但我发现它实际上不起作用。它仅根据级别连接,而不是根据父级的原始ID连接。如果我对我的问题不够清楚,我很抱歉:-(例如,第三行和第五行。在这两种情况下,父级ID都应为2(如第四行)但它显示为1。我想我需要编辑问题以使其更清晰。我现在编辑它,希望它能回答您的问题。已编辑。请让我知道它是否仍然需要澄清。谢谢!看起来非常好!我将在完整的数据集上试用它,如果出现任何问题,我会让您知道。再次感谢!