SQL查询查找x行,将最高值向前移动,中间不包含较低的值

SQL查询查找x行,将最高值向前移动,中间不包含较低的值,sql,sql-server,Sql,Sql Server,我有一张表,左边有两列。 我试图根据一些逻辑实现第三列 逻辑:如果我们选择日期1/1,并且在分数下降之前,继续日期将达到的最高分数将是3/1。得了12分。因此,作为HighestAchievedScore,我们将以1/1获得12分。等等 如果我们在一个下一个得分下降的日期,我的最高得分将是我的下一个得分。就像你在2014年1月3日看到的那样 date score HighestAchieveScore 1/01/2014 10 12 2/01/2014 11

我有一张表,左边有两列。 我试图根据一些逻辑实现第三列

逻辑:如果我们选择日期1/1,并且在分数下降之前,继续日期将达到的最高分数将是3/1。得了12分。因此,作为HighestAchievedScore,我们将以1/1获得12分。等等

如果我们在一个下一个得分下降的日期,我的最高得分将是我的下一个得分。就像你在2014年1月3日看到的那样

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
我希望我解释得足够清楚。
已经感谢您为解决此问题所做的每一项输入。

我不确定这是否可行。。。。但这是一般概念

A.Date 需要进行测试,但必须安装小提琴才能进行测试

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 

假设您希望计算第三列,可以像这样创建表或将该列添加到现有表中,使用函数确定第三列的值:

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

这应适用于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

让我们制作一些测试数据:

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
)
输出:

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

结果在第三列。mssql的哪个版本?2008年,2012年?你是如何在第一次约会时获得12分的高分的,而当时唯一的分数只有10分?第三列是通过记录中的向前推导出的。如果我们想从1/1开始找到最高的得分。我们继续前进,直到比分下降。所以我们检索到的最高值是3/1上的12。这将使我们的最高得分在1/1的12分。这将不起作用,您正在寻找所有未来分数的最大值,此查询中的任何内容都不会考虑分数的下降。分数可以下降,然后高于本地最大值。更正此问题并不能解决此问题。然而,这是一个很好的方法。我知道现在我错过了分数下降的要求。你的CTE只输出两列日期和行。在SELECT子句中,您还引用了分数,这在CTE中不再存在。这也是处理函数的好方法。功能上与另一个答案相同的错误。请参见截图和其他答案
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