减去上一行以在MS SQL中计算列值

问题描述 投票:4回答:2

我下面的数据需要进行格式化以仅连续显示几天而不间断。

例如,我想显示日期为2018-06-182018-06-21的记录,因为这些是连续的日子。但是然后我不想显示日期为2018-06-272018-07-03的行,因为这些天没有序列。Friday-Monday例外,那里会有明显的差距。例如,如果日期为2018-06-21(星期四),2018-06-22(星期五)和2018-06-25(星期一),那么这将是有效的顺序。

2018-6-12018-6-32018-6-4的序列必须被隐藏,因为它已损坏(表中没有2018-6-2的记录)。

我在下面写过,但是无法提供我想要的输出。任何帮助将不胜感激。

select date, diff, Percent_gain, day, month, Year
from (
   select date
      ,datediff(day, '2018-1-29',date) - coalesce(lag(datediff(day, '2018-1-29', date)) over (order by date), 0) as diff
      ,Percent_gain, day, month, year
   from tab
) t1
where t1.diff < 2
   and t1.Percent_gain < 0

enter image description here

输出

enter image description here

sql sql-server date window-functions gaps-and-islands
2个回答
3
投票

您可以使用窗口函数和条件表达式:

select *
from (
    select t.*, lag(date) over(order by date) lag_date
    from mytable t
    where percent_gain < 0
) t
where 
    lag_date is null
    or date = dateadd(day, case when datename(dw, date) = 'Monday' then 3 else 1 end, lag_date)

子查询对percent_gain为负的行进行过滤,并使用lag()检索“上一个”行的date。然后,外部查询根据以下条件再次过滤:

  • 任一行都是“第一个”(即没有上一个日期)

  • 或上一行日期后一天的当前行的日期-如果当前日期是星期一,则除外,在这种情况下,当前日期应比上一日期晚3天

请注意,查询实际上并未使用列daymonthyear;这些看起来像派生值,可以在需要时轻松地即时计算。通常,我们使用datename()来获取日期名称。


0
投票

您可以将其用作查找序列的替代方法。

WITH dates(id ,date)
AS
(
 SELECT 1, '2020-03-10'   UNION 
 SELECT 2, '2020-03-15'   UNION
 SELECT 3, '2020-04-17'   UNION
 SELECT 3, '2020-04-20'   UNION
 SELECT 3, '2020-04-21'   UNION
 SELECT 3, '2020-04-22'   UNION
 SELECT 4, '2020-04-25' 
)

Select A.*,CASE WHEN day_name = 'MONDAY'
                THEN CASE WHEN datediff(d,A.prev_date,A.date) = 3
                          THEN 1
                          ELSE 0 END
                ELSE CASE WHEN datediff(d,A.prev_date,A.date) = 1
                          THEN 1
                          ELSE 0 END
                END AS Is_seq

from (Select t.*, DATENAME(dw,date) as day_name,
             lag(date) over (order by date) as prev_date
      from dates t
     ) A
© www.soinside.com 2019 - 2024. All rights reserved.