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

时间:2017-01-03 14:36:32

标签: sql sql-server-2014 cross-apply

我正在寻找一种方法来获得序列中最低的下一个值。基本上,我有一个Dates的数据集,我希望它在第二天返回,除非它是数据库中的最新日期,然后我希望它返回它。

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

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

5 个答案:

答案 0 :(得分:1)

您可以使用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

答案 1 :(得分:0)

您可以在日期列

上使用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

答案 2 :(得分:0)

我相信你想要:

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

答案 3 :(得分:0)

试试这个

;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 |
+------------+-----+-------------+------------+

答案 4 :(得分:0)

如果您的表永远不会有错过的日期,则以下内容将起作用。

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

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