我现在拥有的是这样的表
Sub foo()
Dim rng As Range
retry:
Set rng = Application.InputBox("Please choose a range", "Obtain Range Object", Type:=8)
If MsgBox("Your choice " & rng.Address & " ?", vbYesNo, "Confirm") = vbYes Then
GoTo continue:
Else
GoTo retry:
End If
continue:
rng.Copy
Worksheets("Sheet2").Range("A1").PasteSpecial xlPasteAll
End Sub
我需要一个新的colum,我将其称为Cycle,它能够“计数”状态从0到不同于0的任何次数(表示此描述的机器进程的开始)并保持不同于0的次数。 (当它返回到0时,它定义进程已完成一个周期)。 我试图使用与变量绑定的计数器来分配一个值,该值根据状态值逐行更改,以将值分配给循环列。
Visual Studio不允许我尝试说固定值已分配给该列,因此它无法分配该值。
有人建议使用排名功能,但我从MS文档中无法清楚地了解它的工作原理,从而无法解决该问题
答案 0 :(得分:2)
必须有一个更漂亮的方法来执行此操作,但此刻我很沮丧。我用您的示例数据创建了一个表变量,您所说的此附加列包含一个日期,可用于订购。由于我缺乏想象力,因此我改用int
,但逻辑应该起作用。
declare @t table (Status int not null, Cycle int not null, ReallyDate int not null)
insert into @t(Status,Cycle,ReallyDate) values
(0,0,1 ), (2,1,2 ), (5,1,3 ), (6,1,4 ), (2,1,5 ), (3,1,6 ),
(0,1,7 ), (1,2,8 ), (2,2,9 ), (5,2,10), (3,2,11), (0,2,12),
(0,2,13), (0,2,14), (1,3,15), (2,3,16), (2,3,17), (5,3,18),
(6,3,19), (2,3,20), (5,3,21), (3,3,22), (0,3,23);
With Numbered as (
select
*,
ROW_NUMBER() OVER (ORDER BY ReallyDate) as rn
from @t
), Roots as (
select
t1.*,
ROW_NUMBER() OVER (ORDER BY t1.ReallyDate) as CyclePrime
from
Numbered t1
left join
Numbered t2
on
t1.rn = t2.rn - 1 and
t2.Status = 0
where
t1.Status = 0 and
t2.rn is null
)
select
n.*,
COALESCE(r.CyclePrime,0) as Cycle
from
Numbered n
left join
Roots r
left join
Roots r_anti
on
r_anti.CyclePrime = r.CyclePrime + 1
on
n.rn > r.rn and
n.rn <= r_anti.rn
当然,我的数据已经有一个我可以使用的列,而不是Numbered
CTE,但是您有一个datetime列,并且需要生成类似rn
的内容。
然后Roots
是一个棘手的人。它标识了0
行,紧接着没有其他0
行。这些我们用来分配周期号。
在最后一个选择中,我们尝试将正在处理的任何行连接到上一个Root
行,并从该行中获取循环号。
结果(包括奖金栏):
Status Cycle ReallyDate rn Cycle
----------- ----------- ----------- -------------------- --------------------
0 0 1 1 0
2 1 2 2 1
5 1 3 3 1
6 1 4 4 1
2 1 5 5 1
3 1 6 6 1
0 1 7 7 1
1 2 8 8 2
2 2 9 9 2
5 2 10 10 2
3 2 11 11 2
0 2 12 12 2
0 2 13 13 2
0 2 14 14 2
1 3 15 15 3
2 3 16 16 3
2 3 17 17 3
5 3 18 18 3
6 3 19 19 3
2 3 20 20 3
5 3 21 21 3
3 3 22 22 3
0 3 23 23 3
答案 1 :(得分:2)
我认为以下是您所追求的:
status=0
和当前记录的status=1
时,将一个添加到循环计数器;对于所有其他值,请取上一条记录的计数器值。 小提琴示例:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=c89c13ede9fe5b752368ded49e7a1c3d
create table TestData
(
DateOrder datetime not null
, StatusId int not null
)
insert TestData(DateOrder, StatusId)
values ('2018-11-06 01:00', 0)
, ('2018-11-06 02:00', 1)
, ('2018-11-06 03:00', 2)
, ('2018-11-06 04:00', 0)
, ('2018-11-06 05:00', 0)
, ('2018-11-06 06:00', 0)
, ('2018-11-06 07:00', 2)
, ('2018-11-06 08:00', 1)
, ('2018-11-06 09:00', 3)
, ('2018-11-06 10:00', 0)
, ('2018-11-06 11:00', 1)
;with cte (DateOrder, StatusId, GeneratedId) as
(
select DateOrder, StatusId, row_number() over (order by DateOrder) GeneratedId
from TestData
)
, cte2 (DateOrder, StatusId, GeneratedId, Cycle) as
(
select DateOrder, StatusId, GeneratedId, 0
from cte
where GeneratedId = 1
union all
select cte.DateOrder, cte.StatusId, cte.GeneratedId
, case
when cte2.StatusId = 0 and cte.StatusId != 0 then cte2.Cycle + 1
else cte2.Cycle
end Cycle
from cte2
inner join cte
on cte.GeneratedId = cte2.GeneratedId + 1
)
select * from cte2 order by DateOrder
答案 2 :(得分:0)
SELECT SUM(循环) FROM表名;
答案 3 :(得分:-1)
选择计数(DISTINCT循环) 周期> 0 FROM表名