依靠积极的变化,减少负面的变化

时间:2015-07-07 12:24:42

标签: mysql arrays sql-server

我有一个更改值的列。 我想通过在每次更改时添加并在每次更改时减去来计算。假设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中完成此类操作,或者我是否最好从数据库中检索数据并在外部执行此类计算。

3 个答案:

答案 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)

你也可以LAGSUMOVER(假设你有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。

您可以定义一个计算列,用于对插入进行计算...

祝你好运!