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