我正在尝试在“x”列中生成数字,考虑字段“eq”中的值,以便它应该为每个记录设置一个数字,直到它满足值“1”,然后下一个行应重置并重新开始计数。我尝试过使用row_number,但问题是我只需要在我需要评估的列中使用1和0,而我使用row_number看到的情况是在列中使用增长值。也尝试了排名,但我还没有设法让它发挥作用。
nInd Fecha Tipo @Inicio @contador_I @Final @contador_F eq x
1 18/03/2002 I 18/03/2002 1 null null 0 1
2 20/07/2002 F 18/03/2002 1 20/07/2002 1 1 2
3 19/08/2002 I 19/08/2002 2 20/07/2002 1 0 1
4 21/12/2002 F 19/08/2002 2 21/12/2002 2 1 2
5 17/03/2003 I 17/03/2003 3 21/12/2002 2 0 1
6 01/04/2003 I 17/03/2003 4 21/12/2002 2 0 2
7 07/04/2003 I 17/03/2003 5 21/12/2002 2 0 3
8 02/06/2003 F 17/03/2003 5 02/06/2003 3 0 4
9 31/07/2003 F 17/03/2003 5 31/07/2003 4 0 5
10 31/08/2003 F 17/03/2003 5 31/08/2003 5 1 6
11 01/09/2005 I 01/09/2005 6 31/08/2003 5 0 1
12 05/09/2005 I 01/09/2005 7 31/08/2003 5 0 2
13 31/12/2005 F 01/09/2005 7 31/12/2005 6 0 3
14 14/01/2006 F 01/09/2005 7 14/01/2006 7 1 4
答案 0 :(得分:3)
还有另一种解决方案:
select
nind, eq, row_number() over (partition by s order by s)
from (
select
nind, eq, coalesce((
select sum(eq) +1 from mytable pre where pre.nInd < mytable.nInd)
,1) s --this is the sum of eq!
from mytable) g
内部子查询在groups
中每次出现1
时依次创建eq
。然后我们可以使用row_number() over partition
来获取我们的计数器。
Here is an example使用Sql Server
答案 1 :(得分:1)
我在这里有两个答案。一个基于ROW_NUMBER()
,另一个基于您的索引(nInd
)。我不确定你的索引是否有差距,所以我也做了ROW_NUMBER()
。
我的表格格式如下 -
myIndex int identity(1,1) NOT NULL
number int NOT NULL
第一个是ROW_NUMBER()
...
WITH rn AS (SELECT *, ROW_NUMBER() OVER (ORDER BY myIndex) AS rn, COUNT(*) AS max
FROM counting c GROUP BY c.myIndex, c.number)
,cte (myIndex, number, level, row) AS (
SELECT r.myIndex, r.number, 1, r.rn + 1 FROM rn r WHERE r.rn = 1
UNION ALL
SELECT r1.myIndex, r1.number,
CASE WHEN r1.number = 0 AND r2.number = 1 THEN 1
ELSE c.level + 1
END,
row + 1
FROM cte c
JOIN rn r1
ON c.row = r1.rn
JOIN rn r2
ON c.row - 1 = r2.rn
)
SELECT c.myIndex, c.number, c.level FROM cte c OPTION (MAXRECURSION 0);
现在索引......
WITH cte (myIndex, number, level) AS (
SELECT c.myIndex + 1, c.number, 1 FROM counting c WHERE c.myIndex = 1
UNION ALL
SELECT c1.myIndex + 1, c1.number,
CASE WHEN c1.number = 0 AND c2.number = 1 THEN 1
ELSE c.level + 1
END
FROM cte c
JOIN counting c1
ON c.myIndex = c1.myIndex
JOIN counting c2
ON c.myIndex - 1 = c2.myIndex
)
SELECT c.myIndex - 1 AS myIndex, c.number, c.level FROM cte c OPTION (MAXRECURSION 0);
答案 2 :(得分:0)
我现在的答案是使用
Cursor
我知道如果有另一种没有光标的解决方案,那么性能方面会更好
这是我的解决方案的快速演示:
-- Create DBTest
use master
Go
Create Database DBTest
Go
use DBTest
GO
-- Create table
Create table Tabletest
(nInd int , eq int)
Go
-- insert dummy data
insert into Tabletest (nInd,eq)
values (1,0),
(2,1),
(3,0),
(4,1),
(5,0),
(6,0),
(7,0),
(8,0),
(9,1),
(8,0),
(9,1)
Create table #Tabletest (nInd int ,eq int ,x int )
go
DECLARE @nInd int , @eq int , @x int
set @x = 1
DECLARE db_cursor CURSOR FOR
SELECT nInd , eq
FROM Tabletest
order by nInd
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @nInd , @eq
WHILE @@FETCH_STATUS = 0
BEGIN
if (@eq = 0)
begin
insert into #Tabletest (nInd ,eq ,x) values (@nInd , @eq , @x)
set @x = @x +1
end
else if (@eq = 1)
begin
insert into #Tabletest (nInd ,eq ,x) values (@nInd , @eq , @x)
set @x = 1
end
FETCH NEXT FROM db_cursor INTO @nInd , @eq
END
CLOSE db_cursor
DEALLOCATE db_cursor
select * from #Tabletest
最终结果集如下:
希望它有所帮助。
答案 3 :(得分:0)
以稍微不同的方式(可能不是这样,但不需要递归CTE的游标),看起来就像在数据集中构建有序组一样。因此,首先找到这些组,然后确定每个组的顺序。
真正的关键是确定查找更正分组的规则。根据您的说明和评论,我猜测分组是从一开始(按nInd
列排序),每行结束时eq
值为1
,所以你可以这样做:
;with ends(nInd, ord) as (
--Find the ending row for each set
SELECT nInd, row_number() over(order by nInd)
FROM mytable
WHERE eq=1
), ranges(sInd, eInd) as (
--Find the previous ending row for each ending row, forming a range for the group
SELECT coalesce(s.nInd,0), e.nInd
FROM ends s
right join ends e on s.ord=e.ord-1
)
然后,使用这些组范围,您可以找到每个组的最终顺序:
select t.nInd, t.Fecha, t.eq
,[x] = row_number() over(partition by sInd order by nInd)
from ranges r
join mytable t on r.sInd < t.nInd
and t.nInd <= r.eInd
order by t.nInd