我有一列可以更改值。我想通过在每一个变化上加法,在每一个变化下减去。假设x[]是我的值,Delta是x元素变化的标志,y[]是我的目标结果或计数。
我们数到下一个δ-1开始计数,然后恢复计数,当增量变回+1。总之,我们通常加起来,直到我们开始减去-1的增量,然后在下一个+1增量时继续加起来。
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中完成,或者我是否最好从数据库中检索数据并在外部执行这种计算。
发布于 2015-07-07 12:39:38
您可以在SQL-Server中使用此查询,假定排序为PK-列:
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预期的结果为9:
OUTER APPLY将当前与前一个记录链接,前一个记录是ID < current.ID最高的记录。它的工作原理类似于LEFT OUTER JOIN。
主要的挑战是上次CTE中的子查询。这对于找到最后一个增量(即<> 0 )是必要的,以确定当前增量是正的还是负的。
发布于 2015-07-07 14:05:11
您还可以在LAG和SUM中使用OVER (假设您拥有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发布于 2015-07-07 12:59:38
您使用sql-server和mysql标记。如果这可以在SQL-Server中完成,则应该查看OVER-子句:https://msdn.microsoft.com/en-us/library/ms189461.aspx。
假设存在排序条件,则可以声明行子句并使用前面行的值。许多SQL-函数允许使用OVER。
您可以定义一个计算列,它在insert上进行计算.
祝好运!
https://stackoverflow.com/questions/31268487
复制相似问题