我有一张这样的表:
Name | FromPoint | TOPoint
--------------------------
A | 0 | 2
A | 2 | 4
B | 2 | 4
A | 4 | 9
B | 5 | 6
如何在T-SQL中编写查询,以递归方式为每个组合Name / FromPoint上的字段FromPoint和ToPoint加入相等性? 最终期望结果的一个例子(考虑上面的数据)是:
Name | FromPoint | ToPoint
----------------------------
A | 0 | 9
B | 2 | 4
B | 5 | 6
答案 0 :(得分:2)
使用一个递归cte,它以frompoint在自连接中没有匹配的元素开头,以便识别起始点。然后通过再次加入来释放中间结果,并仅使用那些在另一个自联接中其topoint匹配无数据的数据。
with cte as (
select r.name, r.frompoint, r.topoint
from #t l
right join
#t r
on l.topoint = r.frompoint
and l.name = r.name
where l.name is null
union all
select l.name, l.frompoint, r.topoint
from cte l
join #t r
on l.topoint = r.frompoint
and l.name = r.name
)
select l.*
from cte l
left join
#t r
on r.name = l.name
and r.frompoint = l.topoint
where r.name is null
答案 1 :(得分:0)
不是一个完整的答案,而是一个开始 我认为这会产生结束点
select left.Name, left.ToPoint
from table left
left join table right
on left.name = right.name
on left.ToPoint = right.FromPoint
where right.FromPoint is null
走回去开始思考需要一个递归的CTE
问题是你可能有像A 1 3那样的序列,所以排序不会对序列进行分组
答案 2 :(得分:0)
另一个不使用递归的选项。它使用内存中的表来编号(Num字段)不同的段。然后它编号每个段的所有成员。最后,它按名称对每个段进行分组,Num提供FromPoint的最小值和ToPoint的最大值
仅当组内没有重叠段时才会起作用。
DECLARE @tbl TABLE(Num INT, Name VARCHAR(50), FromPoint INT, ToPoint INT)
INSERT INTO @tbl
SELECT ROW_NUMBER() OVER (ORDER BY T.Name, T.FromPoint )Num
, T.Name, T.FromPoint, T.ToPoint
FROM TestTable T
WHERE NOT EXISTS(SELECT T.Name FROM TestTable T1
WHERE T.Name=T1.Name AND T.FromPoint=T1.ToPoint)
UNION
SELECT 0 Num, T2.Name, T2.FromPoint, T2.ToPoint
FROM TestTable T2
WHERE EXISTS(SELECT T3.Name FROM TestTable T3
WHERE T2.Name=T3.Name AND T2.FromPoint=T3.ToPoint)
SELECT MyTable.Name, MIN(MyTable.FromPoint)FromPoint, MAX(MyTable.ToPoint)ToPoint
FROM
(SELECT CASE WHEN T.Num=0 THEN
(SELECT TOP 1 TMP.Num FROM @tbl TMP WHERE TMP.Name=T.Name
AND T.FromPoint>TMP.FromPoint AND TMP.Num>0
ORDER BY T.FromPoint-TMP.FromPoint
)
ELSE T.Num END Num
,T.Name, T.FromPoint, T.ToPoint FROM
@tbl T)MyTable
GROUP BY MyTable.Name, MyTable.Num