我想用SQL实现以下任何人都可以帮助:
TOP BOTTOM Rocksymbol
0 5 l
5 10 l
10 15 ml
15 20 ml
20 25 ml
25 30 s
30 35 ml
35 40 ml
40 45 s
应该成为:
TOP BOTTOM Rocksymbol
0 10 l
10 25 ml
25 30 s
30 40 ml
40 45 s
基本上想要为相同的连续RockSymbol分组数据,其中结果中连续块的第一个记录的TOP变为分组记录的TOP,而连续块的最后一个记录的BOTTOM变为分组的BOTTOM记录。
连续的RockSymbol记录数量可能会有所不同。
答案 0 :(得分:0)
更新回答 - 考虑我们可以连续多行使用相同RockSymbol的情况。
SELECT
MIN([top]) as [top],
MAX(bottom) as bottom,
RockSymbol
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY [top]) rowid,
ROW_NUMBER() OVER (PARTITION BY RockSymbol ORDER BY [top]) seqid
,*
FROM
[dbo].[tbl]
) tempt
GROUP BY
RockSymbol,
rowid - seqid
ORDER BY
[top]
SQl小提琴链接http://sqlfiddle.com/#!6/dc3c3/3
编辑:旧答案 - 仅用于了解解决方案的演变
如果你可以改变原始表,那么可能会更新 声明
UPDATE A SET A.[TOP]=B.[TOP] FROM [dbo].[tbl] A INNER JOIN [dbo].[tbl] B ON A.[TOP]=B.BOTTOM AND A.RockSymbol=B.RockSymbol
然后删除额外的行
DELETE FROM [dbo].[tbl] FROM [dbo].[tbl] B LEFT JOIN ( SELECT ROW_NUMBER() OVER(PARTITION BY [Top] ORDER BY Bottom DESC) AS "Rank", [TOP], BOTTOM, RockSymbol FROM [dbo].[tbl]) A ON A.[TOP]=B.[Top] AND A.[Bottom]=B.[Bottom] AND A.RockSymbol=B.RockSymbol WHERE A.Rank>1
如果您无法更新表格,请使用临时表或嵌套
SELECT
查询如下SELECT Q.[TOP], MAX(Q.BOTTOM) as BOTTOM,Q.RockSymbol FROM (SELECT ISNULL(B.[TOP],A.[TOP]) AS [TOP], A.BOTTOM, A.RockSymbol FROM [dbo].[tbl] A LEFT JOIN [dbo].[tbl] B ON A.[TOP]=B.BOTTOM AND A.RockSymbol=B.RockSymbol) Q GROUP BY Q.[TOP], Q.RockSymbol
两个解决方案的Sql fiddles链接都在这里 http://sqlfiddle.com/#!6/e1148/1/0和 http://sqlfiddle.com/#!6/e1148/7
答案 1 :(得分:0)
你需要做这样的事情来实现你正在寻找的东西:
Select [TOP], Case when Rocksymbol = lag(Rocksymbol,1,-1) over (order by [TOP]) then lag([TOP],1,-1) over (order by [TOP]) else -1 end as match into #foobar2
from #foobar
select Min(f1.[TOP]) [TOP], Max(f1.Bottom) Bottom, f1.Rocksymbol
from #foobar f1
Left join #foobar2 f2 on f1.[TOP] = f2.match
Left join #foobar2 f3 on f1.[TOP] = f3.[TOP]
Group by Case when f2.match <> -1 then f1.[TOP] else case when f3.match <> -1 then f3.match else f3.[TOP] end end, Rocksymbol
order by [TOP]
SQL的小提琴就在这里:http://sqlfiddle.com/#!6/b2ef2/2/0
答案 2 :(得分:0)
select IDENTITY(int,1,1) as id ,* into #temp from (
select 0 as 'top', 5 as botton,'l' as rocksymble union all
select 5, 10,'l' union all
select 10, 15,'ml' union all
select 15, 20,'ml' union all
select 20, 25,'s' union all
select 25, 30,'ml' union all
select 30, 35,'s' union all
select 35, 40,'ml' union all
select 40, 45,'ml' union all
select 45, 50,'ml'
) as a
select a.*, b.id as bid into #temp1 from #temp a
left join #temp b
on a.[top] = b.[botton]
and a.rocksymble = b.rocksymble
select a.id,a.rocksymble,a.bid, count(case when b.bid IS null then 1 else null end) grpid into #temp2 from #temp1 a , #temp1 b
where b.id <= a.id
group by a.id,a.rocksymble,a.bid
order by a.id
select min(b.[top]),max(b.botton),b.rocksymble from #temp2 a
join #temp1 b
on a.id = b.id
group by b.rocksymble, a.grpid