Sql e> 无法求和。 1-到SUM和COUNT的负差相当于NOT:它将位符号的值反转为1表示负,0表示正的零。

Sql e> 无法求和。 1-到SUM和COUNT的负差相当于NOT:它将位符号的值反转为1表示负,0表示正的零。,sql,sql-server,olap-cube,Sql,Sql Server,Olap Cube,一种类似于约阿希姆·伊萨克森的方法,但是在CTE中的工作更多,而在主查询中的工作更少 WITH A AS ( SELECT c.CustomerID, c.Points, c.PointsDate , Diff = c.Points - l.Points , l.PointsDate lPointsDate FROM Customer c CROSS APPLY (SELECT TOP 1

一种类似于约阿希姆·伊萨克森的方法,但是在
CTE
中的工作更多,而在主查询中的工作更少

WITH A AS (
  SELECT c.CustomerID, c.Points, c.PointsDate
       , Diff = c.Points - l.Points
       , l.PointsDate lPointsDate
  FROM   Customer c
         CROSS APPLY (SELECT TOP 1
                             Points, PointsDate
                      FROM   Customer cu
                      WHERE  c.CustomerID = cu.CustomerID
                        AND  c.PointsDate > cu.PointsDate
                      ORDER BY cu.PointsDate Desc) l
)
SELECT CustomerID
     , Pos = SUM(Diff * CAST(Sign(Diff) + 1 AS BIT))
     , Neg = SUM(Diff * (1 - CAST(Sign(Diff) + 1 AS BIT)))
     , [Count(pos)] = SUM(0 + CAST(Sign(Diff) + 1 AS BIT))
     , [Count(neg)] = SUM(1 - CAST(Sign(Diff) + 1 AS BIT))
     , Max(Points) [Max], Min(Points) [Min]
FROM   A
GROUP BY CustomerID

删除第一天的条件是
CTE
中的
JOIN
CROSS-APPLY
):第一天没有前一天,因此被过滤掉

在主查询中,我不使用
大小写
来过滤正负差异,而是使用
符号
功能:

  • 此函数返回-1表示负,0表示零,+1表示正
  • 符号(Diff)+1移动值意味着新的返回值为0、1和2
  • CAST
    将负数压缩为
    0
    ,将零或正数压缩为
    1
[Count(pos)]
定义中的
0+
创建一个到整数值的隐式转换,因为
不能求和。

1-
SUM
COUNT
的负差相当于
NOT
:它将
位号的值反转为1表示负,0表示正的零。

我们怎么知道点是负的还是正的?我对立方体一无所知,但听起来你要找的只是一个光标,不是吗?我知道每个人都讨厌游标,但这是我所知道的在不将其加载到客户端机器上的情况下比较连续行的最佳方法(这显然更糟糕)。SQL Server的哪个版本?SQL 2008 R2。点总是正的-我只有“从PointsDate开始的点”,我正在尝试计算变化。那么你如何计算负的值?我们如何知道点是负的还是正的?我对立方体一无所知,但听起来你要找的只是一个光标,不是吗?我知道每个人都讨厌游标,但这是我所知道的在不将其加载到客户端机器上的情况下比较连续行的最佳方法(这显然更糟糕)。SQL Server的哪个版本?SQL 2008 R2。积分总是正的-我只有“截至PointsDate的积分”,我正在尝试计算出变化。那么你如何计算负的值
000021   0   01-JAN-2014
000021  10   02-JAN-2014
000021  20   03-JAN-2014
000021  30   06-JAN-2014
000021  40   07-JAN-2014
000021  10   12-JAN-2014
000034   0   04-JAN-2014
000034  40   05-JAN-2014
000034  20   06-JAN-2014
000034  40   08-JAN-2014
000034  60   10-JAN-2014
000034  80   21-JAN-2014
000034  10   22-JAN-2014
CustomerId  Pos  Neg  Count(pos) Count(neg) Max  Min
000021      40   30           3          1   40   10
000034     100   90           4          2   80   10
WITH cte AS (
  SELECT customerid, points, 
    ROW_NUMBER() OVER (PARTITION BY customerid ORDER BY pointsdate) rn
  FROM mytable
)
SELECT cte.customerid, 
  SUM(CASE WHEN cte.points > old.points THEN cte.points - old.points ELSE 0 END) pos,  
  SUM(CASE WHEN cte.points < old.points THEN old.points - cte.points ELSE 0 END) neg,
  SUM(CASE WHEN cte.points > old.points THEN 1 ELSE 0 END) [Count(pos)],  
  SUM(CASE WHEN cte.points < old.points THEN 1 ELSE 0 END) [Count(neg)],
  MAX(cte.points) max, 
  MIN(cte.points) min
FROM cte
JOIN cte old
  ON cte.rn = old.rn + 1
 AND cte.customerid = old.customerid
GROUP BY cte.customerid
WITH A AS (
  SELECT c.CustomerID, c.Points, c.PointsDate
       , Diff = c.Points - l.Points
       , l.PointsDate lPointsDate
  FROM   Customer c
         CROSS APPLY (SELECT TOP 1
                             Points, PointsDate
                      FROM   Customer cu
                      WHERE  c.CustomerID = cu.CustomerID
                        AND  c.PointsDate > cu.PointsDate
                      ORDER BY cu.PointsDate Desc) l
)
SELECT CustomerID
     , Pos = SUM(Diff * CAST(Sign(Diff) + 1 AS BIT))
     , Neg = SUM(Diff * (1 - CAST(Sign(Diff) + 1 AS BIT)))
     , [Count(pos)] = SUM(0 + CAST(Sign(Diff) + 1 AS BIT))
     , [Count(neg)] = SUM(1 - CAST(Sign(Diff) + 1 AS BIT))
     , Max(Points) [Max], Min(Points) [Min]
FROM   A
GROUP BY CustomerID