【问题标题】:Subtract previous row to calculate column value in MS SQL减去上一行以计算 MS SQL 中的列值
【发布时间】:2020-08-29 23:10:12
【问题描述】:

我有以下数据需要格式化以仅显示连续天而不会中断。

例如,我想显示日期从 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

输出

【问题讨论】:

  • 那么您正在寻找的输出是什么?此外,提供格式良好的 text 或 DDL 和 DML 语句的示例数据要好得多。请不要指望这里的用户会转录您的数据,因为他们不太可能会。
  • 谢谢。我根据提供的样本数据添加了预期的输出。所有按顺序排列的日子都必须可见。
  • 2018-6-1 和 2018-6-3 不是按顺序排列的,但为什么 2018-6-3、2018-6-4 不被视为连续天数。

标签: sql sql-server date window-functions gaps-and-islands


【解决方案1】:

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

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() 来获取日期名称。

【讨论】:

【解决方案2】:

您可以使用它作为查找序列的替代方法。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 2018-04-19
    • 2021-02-22
    • 1970-01-01
    相关资源
    最近更新 更多