我有一张有这种情况的桌子:
使用我的代码
select
ID_A,
ID_B,
Position,
row_number() over (partition by ID_A, ID_B order by position) as row
from
TB_EXAMPLE
order by
ID_A, Position
我添加了一个row_number_a
列,但是我想要row_number_b
的情况。你有什么提示吗?
答案 0 :(得分:3)
这是一个缺口和孤岛问题,您需要在Row_number之前为每行分配一个组号。有几种方法,以下是基于这样的事实,即两个序号之间的差异是相同的,只要其中一个序列没有间隔即可:
position rownum diff
1 1 0
2 1 1
3 1 2
4 1 3
5 2 3
3 3 3
...
22 1 21
23 2 21
24 2 22
现在,如果位置是连续的,则具有相同ID_A和ID_B的所有行将获得相同的差异,并且您可以在PARTITION BY中使用该值:
with cte as
(
select
ID_A
,ID_B
,Position
,position -- if position is not sequential: ROW_NUMBER()over(partition by ID_A order by position)
- ROW_NUMBER()over(partition by ID_A,ID_B order by position) as grp
from TB_EXAMPLE
)
select
ID_A
,ID_B
,Position
,ROW_NUMBER()over(partition by ID_A, ID_B, grp order by position) as rn
from cte
order by ID_A,Position
根据您实际上要删除行的注释,可以简化为检查上一行的值是否与当前行的值相同。
with cte as
(
select
ID_A
,ID_B
,Position
,case when LAG(ID_A)over(order by position) = ID_A
and LAG(ID_B)over(order by position) = ID_B
then 'delete'
else 'keep'
end as flag
from TB_EXAMPLE
)
select *
from cte
where flag = 'delete'
看起来这仅基于ID_B的更改:
with cte as
(
select
ID_A
,ID_B
,Position
,case when LAG(ID_B)over(partition by ID_A order by position) = ID_B
then 'delete'
else 'keep'
end as flag
from TB_EXAMPLE
)
select *
from cte
where flag = 'delete'
答案 1 :(得分:0)
您可以在没有CTE或子查询的情况下解决此问题。
在ID_A上进行分区时,如果先前的ID_B(按位置排序)不同,则row_number为1。 否则,是在ID_A和ID_B上分区的row_number。
SELECT
id_a as id1,
id_b as id2,
position,
(case
when id_b = lag(id_b) over (partition by id_a order by position)
then row_number() over (partition by id_a, id_b order by position)
else 1
end) as row_number_b
FROM TB_EXAMPLE t
ORDER BY id_a, position;
但是要选择要删除的重复项吗?
如果职位没有空缺,那么在这种情况下使用EXISTS也可以。
SELECT *
FROM TB_EXAMPLE t
WHERE exists
(
SELECT 1
FROM TB_EXAMPLE dup
WHERE dup.ID_A = t.ID_A
AND dup.ID_B = t.ID_B
AND dup.position = t.position - 1
);
示例代码段:
declare @TB_EXAMPLE table (id_a uniqueidentifier, id_b uniqueidentifier, position int identity(1,1));
declare @idA uniqueidentifier = newid();
declare @idB_1 uniqueidentifier = newid();
declare @idB_2 uniqueidentifier = newid();
declare @idB_3 uniqueidentifier = newid();
declare @idB_6 uniqueidentifier = newid();
insert into @TB_EXAMPLE (id_a, id_b) values
(@idA,@idB_1),(@idA,@idB_2)
,(@idA,@idB_3),(@idA,@idB_3),(@idA,@idB_3)
,(@idA,newid())
,(@idA,newid())
,(@idA,@idB_6),(@idA,@idB_6)
,(@idA,newid())
,(@idA,@idB_1),(@idA,@idB_2);
SELECT
id_a as id1,
id_b as id2,
position,
(case
when id_b = lag(id_b) over (partition by id_a order by position)
then row_number() over (partition by id_a, id_b order by position)
else 1
end) as row_number_b
FROM @TB_EXAMPLE t
ORDER BY id_a, position;
--
-- The dups, using LAG
--
SELECT TOP 1 WITH TIES *
FROM @TB_EXAMPLE t
ORDER BY IIF(id_b = lag(id_b) over (partition by id_a order by position),1,2);
--
-- The dups, using EXISTS
--
SELECT *
FROM @TB_EXAMPLE t
WHERE exists
(
SELECT 1
FROM @TB_EXAMPLE dup
WHERE dup.ID_A = t.ID_A
AND dup.ID_B = t.ID_B
AND dup.position = t.position - 1
);