我有一个数据集,其中包含12个不同的ID值,以及开始和结束值。我要初始化的是将起始值作为循环的开始参数,将结束值作为最后一个参数。搜索对应的谷值,并找到第一个连续的增长。
下面我发布了一个示例数据集:
create table #sample_data(
ID VARCHAR(10), val1 INT, val2 INT, val3 INT, val4 INT, val5 INT, val6 INT, val7 INT, val8 INT, val9 INT, val10 INT, val11 INT, val12 INT, startValue INT, endValue INT
);
insert into #sample_data values
(1001,3,2,1,0,1,2,3,0,0,0,0,0,1,7),
(1002,1,2,3,4,0,0,0,1,2,3,0,0,1,12),
(1003,0,3,2,1,0,0,0,0,0,0,0,0,1,12),
(1004,0,1,2,3,4,0,0,0,0,0,0,0,3,9),
(1005,1,1,1,1,2,3,2,2,1,1,0,0,1,8);
这是我期望的结果: 对于ID = 1001,我的startValue为1,结束为7,算法将从val1到val7进行比较,以将每个val与下一个val进行比较,并计数一个增量直到结束。 在这种情况下,对于1001,它将为0,因为序列将从减少开始。 对于ID 1002,它也将为3(从val1到val4,当减少时它将在val5处停止) 对于ID 1003,它将为1,因为开始时仅增加 对于ID 1004,它将是2,因为它从3开始并在val9结束 对于ID 1005,它将是2,即从val4到val6的增加
我尝试通过编写CURSOR来执行此操作,但是由于我有超过300K的数据行,因此需要花费数小时来执行。如果您有更好的建议(不使用光标),我会非常感激。
答案 0 :(得分:1)
您可以尝试以下方法。主要部分是每一行都转换为12行表,并带有附加的Increase
列和适当的WHERE
子句。
输入:
CREATE TABLE #SampleData(
ID VARCHAR(10),
val1 INT,
val2 INT,
val3 INT,
val4 INT,
val5 INT,
val6 INT,
val7 INT,
val8 INT,
val9 INT,
val10 INT,
val11 INT,
val12 INT,
startValue INT,
endValue INT
);
INSERT INTO #SampleData
(ID,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12,startValue,endValue)
VALUES
(1001,3,2,1,0,1,2,3,0,0,0,0,0,1,7),
(1002,1,2,3,4,0,0,0,1,2,3,0,0,1,12),
(1003,0,3,2,1,0,0,0,0,0,0,0,0,1,12),
(1004,0,1,2,3,4,0,0,0,0,0,0,0,3,9),
(1005,1,1,1,1,2,3,2,2,1,1,0,0,1,8),
(1006,1,2,3,4,4,0,7,0,9,10,0,12,1,12)
T-SQL:
;WITH PreparationCTE AS (
SELECT
s.ID,
v.Increase,
ROW_NUMBER() OVER (PARTITION BY s.ID ORDER BY v.Nmr) AS Rn1,
SUM(CASE WHEN v.Increase = -1 THEN 0 ELSE 1 END) OVER (PARTITION BY s.ID ORDER BY v.Nmr) AS Rn2
FROM #SampleData s
CROSS APPLY (VALUES
(1, Val1, CASE WHEN Val1 < Val2 THEN 1 WHEN Val1 = Val2 THEN 0 ELSE -1 END),
(2, Val2, CASE WHEN Val2 < Val3 THEN 1 WHEN Val2 = Val3 THEN 0 ELSE -1 END),
(3, Val3, CASE WHEN Val3 < Val4 THEN 1 WHEN Val3 = Val4 THEN 0 ELSE -1 END),
(4, Val4, CASE WHEN Val4 < Val5 THEN 1 WHEN Val4 = Val5 THEN 0 ELSE -1 END),
(5, Val5, CASE WHEN Val5 < Val6 THEN 1 WHEN Val5 = Val6 THEN 0 ELSE -1 END),
(6, Val6, CASE WHEN Val6 < Val7 THEN 1 WHEN Val6 = Val7 THEN 0 ELSE -1 END),
(7, Val7, CASE WHEN Val7 < Val8 THEN 1 WHEN Val7 = Val8 THEN 0 ELSE -1 END),
(8, Val8, CASE WHEN Val8 < Val9 THEN 1 WHEN Val8 = Val9 THEN 0 ELSE -1 END),
(9, Val9, CASE WHEN Val9 < Val10 THEN 1 WHEN Val9 = Val10 THEN 0 ELSE -1 END),
(10, Val10, CASE WHEN Val10 < Val11 THEN 1 WHEN Val10 = Val1 THEN 0 ELSE -1 END),
(11, Val11, CASE WHEN Val11 < Val12 THEN 1 WHEN Val11 = Val2 THEN 0 ELSE -1 END),
(12, Val12, 0)
) v(Nmr, Val, Increase)
WHERE (s.startValue <= v.Nmr) AND (v.Nmr <= s.endValue)
)
SELECT ID, SUM(CASE WHEN (Increase >= 0) AND (Rn1 = Rn2) THEN Increase ELSE 0 END) AS [Count]
FROM PreparationCTE
GROUP BY ID
ORDER BY ID
输出:
----------
ID Count
----------
1001 0
1002 3
1003 1
1004 2
1005 2
1006 3
答案 1 :(得分:0)
如果我正确理解了您的目标,则可以使用如下所示的精选案例:
select result.Id,
-- result.resulttext
LEN(replace(substring(result.resulttext,1, charindex('0', result.resulttext)-1), '1', '')) as finaltesult
from
(select ID,
case when S.val1 <= S.val2 then case when S.val2 >= S.startvalue and S.val2 <= S.endvalue then case when S.val1 < S.val2 then '2' else '1' end else '1' end else '0' end +
case when S.val2 <= S.val3 then case when S.val3 >= S.startvalue and S.val3 <= S.endvalue then case when S.val2 < S.val3 then '2' else '1' end else '1' end else '0' end +
case when S.val3 <= S.val4 then case when S.val4 >= S.startvalue and S.val4 <= S.endvalue then case when S.val3 < S.val4 then '2' else '1' end else '1' end else '0' end +
case when S.val4 <= S.val5 then case when S.val5 >= S.startvalue and S.val5 <= S.endvalue then case when S.val4 < S.val5 then '2' else '1' end else '1' end else '0' end +
case when S.val5 <= S.val6 then case when S.val6 >= S.startvalue and S.val6 <= S.endvalue then case when S.val5 < S.val6 then '2' else '1' end else '1' end else '0' end +
case when S.val6 <= S.val7 then case when S.val6 >= S.startvalue and S.val7 <= S.endvalue then case when S.val6 < S.val7 then '2' else '1' end else '1' end else '0' end +
case when S.val7 <= S.val8 then case when S.val8 >= S.startvalue and S.val8 <= S.endvalue then case when S.val7 < S.val8 then '2' else '1' end else '1' end else '0' end +
case when S.val8 <= S.val9 then case when S.val9 >= S.startvalue and S.val9 <= S.endvalue then case when S.val8 < S.val9 then '2' else '1' end else '1' end else '0' end +
case when S.val9 <= S.val10 then case when S.val10 >= S.startvalue and S.val10 <= S.endvalue then case when S.val9 < S.val10 then '2' else '1' end else '1' end else '0' end +
case when S.val10 <= S.val11 then case when S.val11 >= S.startvalue and S.val11 <= S.endvalue then case when S.val10 < S.val11 then '2' else '1' end else '1' end else '0' end +
case when S.val11 <= S.val12 then case when S.val12 >= S.startvalue and S.val12 <= S.endvalue then case when S.val11 < S.val12 then '2' else '1' end else '1' end else '0' end as resulttext
from @sample_data as S) result
这种情况会将每次转换转换为:
仅是处理结果字符串的问题。 如果要查看“转换后的”结果字符串,请取消注释result.resulttext。