我有一个表格,如屏幕截图所示(前两列),我需要创建一列,就像最后一列一样。我正在尝试计算每个id的连续值的每个序列的长度。
为此,最后一列是必需的。我玩过
extension AVAudioPlayerNode{
var current: TimeInterval{
if let nodeTime = lastRenderTime,let playerTime = playerTime(forNodeTime: nodeTime) {
return Double(playerTime.sampleTime) / playerTime.sampleRate
}
return 0
}
}
,但并没有取得太大的成功,因为圈出的数字(相当可预测)计算为2而不是1。
请帮助!
答案 0 :(得分:3)
首先,我们需要一种方法来定义行的排序方式。例如,在示例数据中,无法确保始终在“第二”行(1, 1)
之前显示“第一”行(1,0)
。
这就是为什么在示例数据中添加了一个Identity列的原因。在实际情况下,详细信息可以按行ID,日期列或其他方式排序,但是您需要确保可以通过唯一条件对行进行排序。
因此,任务非常简单:
就是这样。为了方便您理解逻辑,我使用了通用表表达式并保留了所有列。您可以在单独的语句中随意更改它,并删除一些列。
DECLARE @DataSource TABLE
(
[RowID] INT IDENTITY(1, 1)
,[ID]INT
,[value] INT
);
INSERT INTO @DataSource ([ID], [value])
VALUES (1, 1)
,(1, 0)
,(1, 0)
,(1, 1)
,(1, 1)
,(1, 1)
--
,(2, 0)
,(2, 1)
,(2, 0)
,(2, 0);
WITH DataSourceWithSwitch AS
(
SELECT *
,IIF(LAG([value]) OVER (PARTITION BY [ID] ORDER BY [RowID]) = [value], 0, 1) AS [Switch]
FROM @DataSource
), DataSourceWithGroup AS
(
SELECT *
,SUM([Switch]) OVER (PARTITION BY [ID] ORDER BY [RowID]) AS [Group]
FROM DataSourceWithSwitch
)
SELECT *
,ROW_NUMBER() OVER (PARTITION BY [ID], [Group] ORDER BY [RowID]) AS [GroupRowID]
FROM DataSourceWithGroup
ORDER BY [RowID];
答案 1 :(得分:2)
您想要的结果取决于数据源中 actual 数据的顺序。在SQL中,您对关系进行操作,有时对关系行进行排序。除非您在源表中引入用于对数据进行排序的其他列(例如,自动递增或某个时间戳列),否则在SQL方面,您所需的最终结果不是很明确。
注意:这回答了原始问题,并且未考虑注释中提到的“额外时间戳”列。我没有更新我的答案,因为已经有一个可以接受的答案。
答案 2 :(得分:1)
一种解决方法是通过递归CTE:
There is no option, use [^] or [\s\S] / [\d\D] / [\w\W] instead of a dot.
这将返回以下内容:
create table #tmp (i int identity,id int, value int, rn int);
insert into #tmp (id,value) VALUES
(1,1),(1,0),(1,0),(1,1),(1,1),(1,1),
(2,0),(2,1),(2,0),(2,0);
WITH numbered AS (
SELECT i,id,value, 1 seq FROM #tmp WHERE i=1 UNION ALL
SELECT a.i,a.id,a.value, CASE WHEN a.id=b.id AND a.value=b.value THEN b.seq+1 ELSE 1 END
FROM #tmp a INNER JOIN numbered b ON a.i=b.i+1
)
SELECT * FROM numbered -- OPTION (MAXRECURSION 1000)
在此处查看我的小演示:https://rextester.com/ZZEIU93657
CTE起作用的先决条件是有序列表(例如其中有i id value seq
1 1 1 1
2 1 0 1
3 1 0 2
4 1 1 1
5 1 1 2
6 1 1 3
7 2 0 1
8 2 1 1
9 2 0 1
10 2 0 2
列的表)作为源。在我的示例中,我为此介绍了列identity
。首先,我需要找到源表的第一个条目。就我而言,这是带有i
的条目。
对于更长的源表,您可能会遇到递归限制错误,因为i=1
的默认值为100。在这种情况下,您应该取消上面MAXRECURSION
子句后面的OPTION设置的注释。您可以将其设置为更高的值(如图所示),也可以通过将其设置为0完全关闭它。
答案 3 :(得分:0)
恕我直言,使用游标和循环更容易做到这一点。
也许有一种方法可以通过自连接完成工作
declare @t table (id int, val int)
insert into @t (id, val)
select 1 as id, 1 as val
union all select 1, 0
union all select 1, 0
union all select 1, 1
union all select 1, 1
union all select 1, 1
;with cte1 (id , val , num ) as
(
select id, val, row_number() over (ORDER BY (SELECT 1)) as num from @t
)
, cte2 (id, val, num, N) as
(
select id, val, num, 1 from cte1 where num = 1
union all
select t1.id, t1.val, t1.num,
case when t1.id=t2.id and t1.val=t2.val then t2.N + 1 else 1 end
from cte1 t1 inner join cte2 t2 on t1.num = t2.num + 1 where t1.num > 1
)
select * from cte2