首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >数一数积极的变化,减少消极的变化。

数一数积极的变化,减少消极的变化。
EN

Stack Overflow用户
提问于 2015-07-07 12:24:41
回答 3查看 174关注 0票数 2

我有一列可以更改值。我想通过在每一个变化上加法,在每一个变化下减去。假设x[]是我的值,Delta是x元素变化的标志,y[]是我的目标结果或计数。

我们数到下一个δ-1开始计数,然后恢复计数,当增量变回+1。总之,我们通常加起来,直到我们开始减去-1的增量,然后在下一个+1增量时继续加起来。

代码语言:javascript
运行
复制
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中完成,或者我是否最好从数据库中检索数据并在外部执行这种计算。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-07-07 12:39:38

您可以在SQL-Server中使用此查询,假定排序为PK-列:

代码语言:javascript
运行
复制
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 )是必要的,以确定当前增量是正的还是负的。

票数 4
EN

Stack Overflow用户

发布于 2015-07-07 14:05:11

您还可以在LAGSUM中使用OVER (假设您拥有Server 2012或更高版本)。

样本数据

代码语言:javascript
运行
复制
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);

查询

代码语言:javascript
运行
复制
;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

输出

代码语言:javascript
运行
复制
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
票数 3
EN

Stack Overflow用户

发布于 2015-07-07 12:59:38

您使用sql-server和mysql标记。如果这可以在SQL-Server中完成,则应该查看OVER-子句:https://msdn.microsoft.com/en-us/library/ms189461.aspx

假设存在排序条件,则可以声明行子句并使用前面行的值。许多SQL-函数允许使用OVER。

您可以定义一个计算列,它在insert上进行计算.

祝好运!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31268487

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档