减去上一行以计算 MS SQL 中的列值
Subtract previous row to calculate column value in MS SQL
我有以下数据需要格式化以仅显示不间断的连续几天。
例如,我想显示日期从 2018-06-18
到 2018-06-21
的记录,因为这些是连续的几天。但是后来我不想显示日期为 2018-06-27
或 2018-07-03
的行,因为这些天没有序列。
Friday-Monday
例外,那里会有明显的差距。例如,如果日期是 2018-06-21
(星期四)、2018-06-22
(星期五)和 2018-06-25
(星期一),那么这将是一个有效的序列。
2018-6-1
、2018-6-3
、2018-6-4
的序列必须隐藏,因为它已损坏(table 中没有 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
输出
您可以使用 window 函数和条件表达式:
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()
检索"previous"行的date
。然后,外部查询根据以下条件再次过滤:
要么该行是 "first" 行(即没有之前的日期)
或当前行的日期比上一个日期晚一天 - 如果当前日期是星期一除外,在这种情况下当前日期应比上一个日期晚 3 天
请注意,查询实际上并未使用列 day
、month
和 year
;这些看起来像派生值,可以在需要时轻松地即时计算。通常,我们使用 datename()
来获取日期名称。
您可以使用它作为查找序列的替代方法。
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
我有以下数据需要格式化以仅显示不间断的连续几天。
例如,我想显示日期从 2018-06-18
到 2018-06-21
的记录,因为这些是连续的几天。但是后来我不想显示日期为 2018-06-27
或 2018-07-03
的行,因为这些天没有序列。
Friday-Monday
例外,那里会有明显的差距。例如,如果日期是 2018-06-21
(星期四)、2018-06-22
(星期五)和 2018-06-25
(星期一),那么这将是一个有效的序列。
2018-6-1
、2018-6-3
、2018-6-4
的序列必须隐藏,因为它已损坏(table 中没有 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
输出
您可以使用 window 函数和条件表达式:
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()
检索"previous"行的date
。然后,外部查询根据以下条件再次过滤:
要么该行是 "first" 行(即没有之前的日期)
或当前行的日期比上一个日期晚一天 - 如果当前日期是星期一除外,在这种情况下当前日期应比上一个日期晚 3 天
请注意,查询实际上并未使用列 day
、month
和 year
;这些看起来像派生值,可以在需要时轻松地即时计算。通常,我们使用 datename()
来获取日期名称。
您可以使用它作为查找序列的替代方法。
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