具有下一个可能值最低的列(自连接 table)

Have a column with the lowest possible next value (self-joining a table)

我正在寻找一种方法来获取序列中的下一个最低值。基本上,我有一个日期数据集,我希望它在第二天成为 return,除非它是数据库中的最新日期,那么我希望它成为 return 这个。

我当前的查询看起来像这样并且几乎可以工作 - 当然直到我想要最新的可能值而不是下一个:

SELECT
  a.date,
  a.key,
  a.description,
  b.date NextDate
FROM
  my_table a
  CROSS APPLY (SELECT TOP 1
  b.date
FROM
  my_table b
WHERE
  a.key = b.key AND
  a.date < b.date) b

示例数据:

+----------+-----+-------------+
|   date   | key | description |
+----------+-----+-------------+
| 20170101 | atx | xxx         |
| 20161228 | hfn | xxx         |
| 20161222 | ktn | xxx         |
| 20161214 | yqe | xxx         |
| 20161204 | olp | xxx         |
| 20161122 | bux | xxx         |
+----------+-----+-------------+

结果应该是这样的:

+----------+-----+-------------+----------+
|   date   | key | description | NextDate |
+----------+-----+-------------+----------+
| 20170101 | atx | xxx         | 20170101 |
| 20161228 | hfn | xxx         | 20170101 |
| 20161222 | ktn | xxx         | 20161228 |
| 20161214 | yqe | xxx         | 20161222 |
| 20161204 | olp | xxx         | 20161214 |
| 20161122 | bux | xxx         | 20161204 |
+----------+-----+-------------+----------+

您可以使用 case 表达式来执行此操作。

SELECT
  a.date,
  a.key,
  a.description,
  case when date = max(a.date) over() then date
  else (select min(date) from mytable b where a.date < b.date)  end as NextDate
FROM
  my_table a

您可以在日期列

上使用lag
select t.*,
    lag(date, 1, date) over (order by date desc) nextdate
from 
(SELECT
  a.date,
  a.key,
  a.description,
  b.date NextDate
FROM
  my_table a
  CROSS APPLY (SELECT TOP 1
  b.date
FROM
  my_table b
WHERE
  a.key = b.key AND
  a.date < b.date) b) t

我相信你想要:

select a.*,
       coalesce(lead(date) over (order by date),
                max(date) over ()
               )
from my_table a;

试试这个

;with cte as
(
SELECT [DATE] = Cast([date] AS DATE),
       [key],
       [description],
       Lag([date])OVER(ORDER BY  Cast([date] AS DATE) DESC) AS prev_date
FROM   ( VALUES ('20170101','atx','xxx'),
                ('20161228','hfn','xxx'),
                ('20161222','ktn','xxx'),
                ('20161214','yqe','xxx'),
                ('20161204','olp','xxx'),
                ('20161122','bux','xxx')) tc ([date], [key], [description])
)
SELECT [date],
       [Key],
       [Description],
       NextDate = Iif([date] < prev_date, prev_date, [date])
FROM   cte 

结果:

+------------+-----+-------------+------------+
|    date    | Key | Description |  NextDate  |
+------------+-----+-------------+------------+
| 2017-01-01 | atx | xxx         | 2017-01-01 |
| 2016-12-28 | hfn | xxx         | 2017-01-01 |
| 2016-12-22 | ktn | xxx         | 2016-12-28 |
| 2016-12-14 | yqe | xxx         | 2016-12-22 |
| 2016-12-04 | olp | xxx         | 2016-12-14 |
| 2016-11-22 | bux | xxx         | 2016-12-04 |
+------------+-----+-------------+------------+

如果您的 table 从不缺少日期,则以下方法可行。

SELECT CONVERT(DATE,CONVERT(CHAR(10),a.date,120))
,a.key,
,a.description,
,CASE 
    WHEN (SELECT MAX(a.date) FROM my_table a) <> AsAtDateID 
        THEN DATEADD(DAY,1,CONVERT(DATE,CONVERT(CHAR(10),a.date,120)))--This could be a select statement
    ELSE CONVERT(DATE,CONVERT(CHAR(10),a.date,120))
END 
FROM my_table a
ORDER BY Date DESC

或者,如果缺少日期,那么您可以在 CASE 中使用 SQL 语句来获取下一个最高日期。

SELECT MIN(Date) FROM my_table WHERE Date > a.Date

不是最高性能的代码,但在我们谈论日期 table 时看到它会起作用。我相信 CTE 也可以用来做这件事,如果你需要更多的性能 使用 SQL 2008,不带 LEAD 和 LAG 等...