【发布时间】:2018-10-29 02:29:43
【问题描述】:
我想查找第一次和最后一次出现值之间的行数。但是,当它们之间有五个或更多不同值的记录时,停止计数。
因此,如果最后一次出现在今天,第一次出现在昨天,则结果将是 2(今天加上昨天)。
如果最后一次出现是今天,第一次出现是 8 天前,并且两者之间没有出现,则结果将为“1”。但是,如果在 3 天前再次出现,则结果将是 4(3+2+1 天前加上今天)。
我希望这是有道理的。
这是我的数据
Date City Weather
==============================
2018-08-11 Ankara Sun
2018-08-10 Ankara Sun
2018-08-09 Ankara Sun
2018-08-08 Ankara Sun
2018-08-07 Ankara Sun
2018-08-06 Ankara Sun
2018-08-05 Ankara Rain
2018-08-04 Ankara Clouds
2018-08-03 Ankara Rain
2018-08-02 Ankara Sun
2018-08-01 Ankara Sun
2018-08-11 Cairo Clouds
2018-08-10 Cairo Sun
2018-08-09 Cairo Sun
2018-08-08 Cairo Sun
2018-08-07 Cairo Sun
2018-08-06 Cairo Sun
2018-08-05 Cairo Clouds
2018-08-04 Cairo Sun
2018-08-03 Cairo Sun
2018-08-02 Cairo Sun
2018-08-01 Cairo Sun
我需要的是一个查询,它返回给定城市的日期和当天的天气日期以及自从这种天气第一次发生以来的天数。但是,当间隔超过 5 天时,计数会从 1 重新开始。
就像在11th Aug 上查询Ankara 时一样,它会返回11,因为距离Sun 首次出现已经过去了11 天(包括今天)。
但是对于11th Aug 上的Cairo,它将返回1 而不是7,因为在8 月5 日的Clouds 和今天的Clouds 之间已经过去了5 天以上。
我已经尝试了很多关于 first_value()、LEAD、LAG 和 ROW_NUMBER 的方法,但没有任何意义,因为这一切都失败了。
反正就是这样……
select
city, val,datediff(day, min(datadate), '2018-10-30') + 1 as DaysPresent
from d
where val = last_val
group by city,val;
或者...
select
date, city, weather, datediff(day,ca.prior,d.date)+1 as daysPresent
from d
cross apply (
select min(prev.date) as prior
from d as prev
where prev.city = d.city
and prev.date between dateadd(day,-4,d.date) and dateadd(day,0,d.date)
and prev.weather = d.weather
) ca
order by city,date
预期结果
+----+---------------------+--------+---------+----------------+-------------+----------+----------------------------
| | date | city | weather | prior_the_same | prior_types |expected | why?
+----+---------------------+--------+---------+----------------+-------------+----------+----------------------------
| 1 | 11.08.2018 00:00:00 | Ankara | Sun | 5 | 2 | 11 | 11t day since 1st time Sun
| 2 | 10.08.2018 00:00:00 | Ankara | Sun | 4 | 3 | 10 | 10t day since 1st time Sun
| 3 | 09.08.2018 00:00:00 | Ankara | Sun | 7 | 3 | 9 | 9th day since 1st time Sun
| 4 | 08.08.2018 00:00:00 | Ankara | Sun | 7 | 3 | 8 | 8th day since 1st time Sun
| 5 | 07.08.2018 00:00:00 | Ankara | Sun | 6 | 3 | 7 | 7th day since 1st time Sun
| 6 | 06.08.2018 00:00:00 | Ankara | Sun | 5 | 3 | 6 | 6th day since 1st time Sun ( <5 days gap since last Sun keeps counting )
| 7 | 05.08.2018 00:00:00 | Ankara | Rain | 2 | 3 | 3 | 3rd day since 1st time Rain
| 8 | 04.08.2018 00:00:00 | Ankara | Clouds | 0 | 3 | 1 | 1st day Clouds
| 9 | 03.08.2018 00:00:00 | Ankara | Rain | 0 | 2 | 1 | 1st day Rain
| 10 | 02.08.2018 00:00:00 | Ankara | Sun | 1 | 0 | 2 | 2nd day since 1st time Sun
| 11 | 01.08.2018 00:00:00 | Ankara | Sun | 0 | 0 | 1 | 1st day Sun
| 12 | 11.08.2018 00:00:00 | Cairo | Clouds | 6 | 6 | 1 | 1st time Clouds ( >5 days gap since last Clouds resets the count )
| 13 | 10.08.2018 00:00:00 | Cairo | Sun | 7 | 1 | 10 | 10t day since 1st time Sun
| 14 | 09.08.2018 00:00:00 | Cairo | Sun | 7 | 1 | 9 | 9th day since 1st time Sun
| 15 | 08.08.2018 00:00:00 | Cairo | Sun | 7 | 1 | 8 | 8th day since 1st time Sun
| 16 | 07.08.2018 00:00:00 | Cairo | Sun | 6 | 1 | 7 | 7th day since 1st time Sun
| 17 | 06.08.2018 00:00:00 | Cairo | Sun | 5 | 1 | 6 | 6th day since 1st time Sun ( <5 days gap since last Sun keeps counting )
| 18 | 05.08.2018 00:00:00 | Cairo | Clouds | 0 | 4 | 1 | 1st time Clouds
| 19 | 04.08.2018 00:00:00 | Cairo | Sun | 3 | 0 | 4 | 4th day since 1st time Sun
| 20 | 03.08.2018 00:00:00 | Cairo | Sun | 2 | 0 | 3 | 3rd day since 1st time Sun
| 21 | 02.08.2018 00:00:00 | Cairo | Sun | 1 | 0 | 2 | 2nd day since 1st time Sun
| 22 | 01.08.2018 00:00:00 | Cairo | Sun | 0 | 0 | 1 | 1st day Sun
+----+---------------------+--------+---------+----------------+-------------+----------+----------------------------
【问题讨论】:
-
我认为你应该更好地展示涵盖所有边缘情况的样本数据。你的逻辑对我来说并不完全清楚。
-
@Peete 。 . .我同意蒂姆的观点。这些规则似乎相当神秘。为他们提供某种理由会有所帮助,示例数据上显示结果的附加列也会有所帮助。
-
在两个问题前the cross apply seen above was proposed 被接受,然后另一个变体被接受,尽管使用
dateadd(day,0,d.date)没有意义,只使用d.date没有该功能。 -
我添加了一个结果表,其中解释了为什么结果会像所描述的业务逻辑那样。感谢您的意见,帮助我更好地在这里提问。
标签: sql sql-server lag row-number lead