我有一个更改值的列。
我想通过在每次更改时添加并在每次更改时减去来计算。假设x[]
是我的值,Delta
是x元素变化的标志,y[]
是我的目标结果或计数。
我们计算直到我们开始倒计时的下一个delta -1,然后当delta变回+1时我们恢复计数。总之,我们正常添加,直到我们有一个delta为-1,那时我们开始减去,然后在下一个+1 delta继续累加。
x: 1, 3, 4, 4, 4, 5, 5, 3, 3, 4, 5, 5, 6, 5, 4, 4, 4, 3, 4, 5, 6, 7, 8
Delta: 0, 1, 1, 0, 0, 1, 0, -1, 0, 1, 1, 0, 1, -1, -1, 0, 0, -1, 1, 1, 1, 1, 1
y: 1, 2, 3, 4, 5, 6, 7, 6, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 5, 6, 7, 8, 9
我的数组的长度是数百万行,效率很重要。不确定是否应该在SQL
中完成此类操作,或者我是否最好从数据库中检索数据并在外部执行此类计算。
答案 0 :(得分:4)
您可以在SQL-Server中使用此查询,假定订购的PK列:
package require Tk
toplevel .my
<something with> .my
pack [label .my.l -text "hallo"]
结果是预期的9:
WITH CTE AS
(
SELECT t.ID, t.Value,
LastValue = Prev.Value,
Delta = CASE WHEN Prev.Value IS NULL
OR t.Value > Prev.Value THEN 1
WHEN t.Value = Prev.Value THEN 0
WHEN t.Value < Prev.Value THEN -1 END
FROM dbo.TableName t
OUTER APPLY (SELECT TOP 1 t2.ID, t2.Value
FROM dbo.TableName t2
WHERE t2.ID < t.ID
ORDER BY t2.ID DESC) Prev
)
, Changes AS
(
SELECT CTE.ID, CTE.Value, CTE.LastValue, CTE.Delta,
Change = CASE WHEN CTE.Delta <> 0 THEN CTE.Delta
ELSE (SELECT TOP 1 CTE2.Delta
FROM CTE CTE2
WHERE CTE2.ID < CTE.ID
AND CTE2.Delta <> 0
ORDER BY CTE2.ID DESC) END
FROM CTE
)
SELECT SUM(Change) FROM Changes c
将当前与前一记录链接起来,前一记录是具有最高ID <1的记录。 OUTER APPLY
。它的工作方式类似于current.ID
。
主要挑战是最后一次CTE中的子查询。必须找到LEFT OUTER JOIN
的最后一个增量来确定当前增量是正还是负。
答案 1 :(得分:3)
你也可以LAG
和SUM
与OVER
(假设你有SQL Server 2012或更高版本)这样使用。
示例数据
DECLARE @Table1 TABLE (ID int identity(1,1), [x] int);
INSERT INTO @Table1([x])
VALUES (1),(3),(4),(4),(4),(5),(5),(3),(3),(4),(5),(5),(6),(5),(4),(4),(4),(3),(4),(5),(6),(7),(8);
<强>查询强>
;WITH T1 as
(
SELECT ID,x,ISNULL(LAG(x) OVER(ORDER BY ID ASC),x - 1) as PrevVal
FROM @Table1
), T2 as
(
SELECT ID,x,PrevVal,CASE WHEN x > PrevVal THEN 1 WHEN x < PrevVal THEN -1 ELSE 0 END as delta
FROM T1
)
SELECT ID,x,SUM(COALESCE(NULLIF(T2.delta,0),TI.delta,0))OVER(ORDER BY ID) as Ordered
FROM T2 OUTER APPLY (SELECT TOP 1 delta from T2 TI WHERE TI.ID < T2.ID AND TI.x = T2.x AND TI.delta <> 0 ORDER BY ID DESC) as TI
ORDER BY ID
<强>输出强>
ID x Ordered
1 1 1
2 3 2
3 4 3
4 4 4
5 4 5
6 5 6
7 5 7
8 3 6
9 3 5
10 4 6
11 5 7
12 5 8
13 6 9
14 5 8
15 4 7
16 4 6
17 4 5
18 3 4
19 4 5
20 5 6
21 6 7
22 7 8
23 8 9
答案 2 :(得分:0)
您使用sql-server和mysql标记。如果可以在SQL-Server中完成,您应该查看OVER子句:https://msdn.microsoft.com/en-us/library/ms189461.aspx
假设有一个排序标准,则可以声明一个ROW子句并使用前一行的值。许多SQL函数允许使用OVER。
您可以定义一个计算列,用于对插入进行计算...
祝你好运!