我有一张左2列的表格。 我试图基于某种逻辑来实现第3列。
逻辑:如果我们采取日期1/1并且进一步达到最高分,那么在分数下降之前进一步的分数将是3/1。得分为12.因此,作为HighestAchievedScore,我们将检索12为1/1。等等。
如果我们处于下一个得分下降的日期,我的最高成绩将是我的下一个得分。就像你在2014年3月1日看到的那样
date score HighestAchieveScore
1/01/2014 10 12
2/01/2014 11 12
3/01/2014 12 10
4/01/2014 10 11
5/01/2014 11 9
6/01/2014 9 8
7/01/2014 8 9
8/01/2014 9 9
我希望我能够清楚地解释清楚。 非常感谢您解决问题的所有输入。
答案 0 :(得分:1)
让我们制作一些测试数据:
DECLARE @Score TABLE
(
ScoreDate DATETIME,
Score INT
)
INSERT INTO @Score
VALUES
('01-01-2014', 10),
('01-02-2014', 11),
('01-03-2014', 12),
('01-04-2014', 10),
('01-05-2014', 11),
('01-06-2014', 9),
('01-07-2014', 8),
('01-08-2014', 9);
现在我们要对行进行编号,然后链接到下一行,看看我们是否还在上升
WITH ScoreRows AS
(
SELECT
s.ScoreDate,
s.Score,
ROW_NUMBER() OVER (ORDER BY ScoreDate) RN
FROM @Score s
),
ScoreUpDown AS
(
SELECT p.ScoreDate,
p.Score,
p.RN,
CASE WHEN p.Score < n.Score THEN 1 ELSE 0 END GoingUp,
ISNULL(n.Score, p.Score) NextScore
FROM ScoreRows p
LEFT JOIN ScoreRows n
ON n.RN = p.RN + 1
)
我们以递归方式查找下一行的数据,然后将该值作为我们仍在上升的行的最大值。否则,我们将得分用于下一行。
SELECT
s.ScoreDate,
s.Score,
CASE WHEN s.GoingUp = 1 THEN d.Score ELSE s.NextScore END Test
FROM ScoreUpDown s
OUTER APPLY
(
SELECT TOP 1 * FROM ScoreUpDown d
WHERE d.ScoreDate > s.ScoreDate
AND GoingUp = 0
) d;
输出:
ScoreDate Score Test
2014-01-01 00:00:00.000 10 12
2014-01-02 00:00:00.000 11 12
2014-01-03 00:00:00.000 12 10
2014-01-04 00:00:00.000 10 11
2014-01-05 00:00:00.000 11 9
2014-01-06 00:00:00.000 9 8
2014-01-07 00:00:00.000 8 9
2014-01-08 00:00:00.000 9 9
答案 1 :(得分:0)
我不确定这会起作用......但这是一般概念。
自我加入A.Date&lt; B.Date获得最大分数,但在CTE中指定的rowID上使用coalesce和第3个self连接来确定分数是否在下一个记录中下降,如果它确实合并了该分数,否则使用最大分数。 / p>
需要测试,但必须设置一个小提琴这样做..
WITH CTE as
(SELECT Date, Score, ROW_NUMBER() OVER(ORDER BY A.Date ASC) AS Row FROM tableName)
SELECT A.Date, A.Score, coalesce(c.score, Max(A.Score)) as HighestArchievedScore
FROM CTE A
LEFT JOIN CTE B
on A.Date < B.Date
LEFT JOIN CTE C
on A.Row+1=B.Row
and A.Score > C.Score
GROUP BY A.DATE,
A.SCORE
答案 2 :(得分:0)
假设您想要计算第三列,您可以像这样创建表(或将列添加到现有表中),使用function
来确定第三列的值:
Create Function dbo.fnGetMaxScore(@Date Date)
Returns Int
As Begin
Declare @Ret Int
Select @Ret = Max(Score)
From YourTable
Where Date > @Date
Return @Ret
End
Create Table YourTable
(
Date Date,
Score Int,
HighestAchieveScore As dbo.fnGetMaxScore(Date)
)
答案 3 :(得分:0)
这应该适用于SQL Server 2012但不适用于早期版本:
WITH cte AS (
SELECT date,
LEAD(score) OVER (ORDER BY date) nextScore
FROM yourTable
)
SELECT t.date, score,
CASE
WHEN nextScore < score THEN nextScore
ELSE (
SELECT ISNULL(MAX(t1.score), t.score)
FROM yourTable t1
JOIN cte ON t1.date = cte.date
WHERE t1.date > t.date
AND ISNULL(nextScore, 0) < score
)
END AS HighestAchieveScore
FROM yourTable t
JOIN cte ON t.date = cte.date