在SQL Server中,我试图计算自过去5天首次观察到与今天相同的天气(今天假设是2018年8月6日)以来的天数。每个镇。
数据如下:
+---------+---------+--------+--------+--------+ | Date | Toronto | Cairo | Zagreb | Ankara | +---------+---------+--------+--------+--------+ | 1.08.18 | Rain | Sun | Clouds | Sun | | 2.08.18 | Sun | Sun | Clouds | Sun | | 3.08.18 | Rain | Sun | Clouds | Rain | | 4.08.18 | Clouds | Sun | Clouds | Clouds | | 5.08.18 | Rain | Clouds | Rain | Rain | | 6.08.18 | Rain | Sun | Sun | Sun | +---------+---------+--------+--------+--------+
这需要执行得很好,但到目前为止,我只想针对每个镇进行单个查询(并且将会有数十个镇,而不仅仅是四个镇)。这行得通,但不会扩展。
这是多伦多的那个…
SELECT DATEDIFF(DAY, MIN([Date]), GETDATE()) + 1 FROM (SELECT TOP 5 * FROM Weather WHERE [Date] <= GETDATE() ORDER BY [Date] DESC) a WHERE Toronto = (SELECT TOP 1 Toronto FROM Weather WHERE DataDate = GETDATE())
…正确返回4,因为今天有雨,而过去5天内第一次下雨是8月3日。
但是我想要返回的是一个像这样的表:
+---------+-------+--------+--------+ | Toronto | Cairo | Zagreb | Ankara | +---------+-------+--------+--------+ | 4 | 5 | 1 | 5 | +---------+-------+--------+--------+
这怎么可能?
您确实不想尝试对数据透视表执行此操作,尽管您声明数据不是以这种方式存储的,但您没有向我们展示如何以列为中心到达城市的透视图。耻辱。
因此,我已经在一个公用表表达式中“取消透视”了该样本,然后使用apply operator来对前5天相同天气的先前发生次数进行计数。看来您知道如何旋转,我将其留给您来旋转最终结果。
apply operator
with cte as ( select date, city, weather FROM ( SELECT * from mytable ) AS cp UNPIVOT ( Weather FOR City IN (Toronto, Cairo, Zagreb, Ankara) ) AS up ) select date, city, weather, ca.prior from cte cross apply ( select count(*) as prior from cte as prev where prev.city = cte.city and prev.date between dateadd(day,-6,cte.date) and dateadd(day,-1,cte.date) and prev.weather = cte.weather ) ca
使用此样本数据:
CREATE TABLE mytable( Date date NOT NULL ,Toronto VARCHAR(9) NOT NULL ,Cairo VARCHAR(9) NOT NULL ,Zagreb VARCHAR(9) NOT NULL ,Ankara VARCHAR(9) NOT NULL ); INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180801','Rain','Sun','Clouds','Sun'); INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180802','Sun','Sun','Clouds','Sun'); INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180803','Rain','Sun','Clouds','Rain'); INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180804','Clouds','Sun','Clouds','Clouds'); INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180805','Rain','Clouds','Rain','Rain'); INSERT INTO mytable(Date,Toronto,Cairo,Zagreb,Ankara) VALUES ('20180806','Rain','Sun','Sun','Sun');
上面的查询产生了以下结果:
+----+---------------------+---------+---------+-------+ | | date | city | weather | prior | +----+---------------------+---------+---------+-------+ | 1 | 01.08.2018 00:00:00 | Ankara | Sun | 0 | | 2 | 02.08.2018 00:00:00 | Ankara | Sun | 1 | | 3 | 03.08.2018 00:00:00 | Ankara | Rain | 0 | | 4 | 04.08.2018 00:00:00 | Ankara | Clouds | 0 | | 5 | 05.08.2018 00:00:00 | Ankara | Rain | 1 | | 6 | 06.08.2018 00:00:00 | Ankara | Sun | 2 | | 7 | 01.08.2018 00:00:00 | Cairo | Sun | 0 | | 8 | 02.08.2018 00:00:00 | Cairo | Sun | 1 | | 9 | 03.08.2018 00:00:00 | Cairo | Sun | 2 | | 10 | 04.08.2018 00:00:00 | Cairo | Sun | 3 | | 11 | 05.08.2018 00:00:00 | Cairo | Clouds | 0 | | 12 | 06.08.2018 00:00:00 | Cairo | Sun | 4 | | 13 | 01.08.2018 00:00:00 | Toronto | Rain | 0 | | 14 | 02.08.2018 00:00:00 | Toronto | Sun | 0 | | 15 | 03.08.2018 00:00:00 | Toronto | Rain | 1 | | 16 | 04.08.2018 00:00:00 | Toronto | Clouds | 0 | | 17 | 05.08.2018 00:00:00 | Toronto | Rain | 2 | | 18 | 06.08.2018 00:00:00 | Toronto | Rain | 3 | | 19 | 01.08.2018 00:00:00 | Zagreb | Clouds | 0 | | 20 | 02.08.2018 00:00:00 | Zagreb | Clouds | 1 | | 21 | 03.08.2018 00:00:00 | Zagreb | Clouds | 2 | | 22 | 04.08.2018 00:00:00 | Zagreb | Clouds | 3 | | 23 | 05.08.2018 00:00:00 | Zagreb | Rain | 0 | | 24 | 06.08.2018 00:00:00 | Zagreb | Sun | 0 | +----+---------------------+---------+---------+-------+
自首次发生以来的天数(过去5天内)
select date, city, weather, datediff(day,ca.prior,cte.date) as prior from cte cross apply ( select min(prev.date) as prior from cte as prev where prev.city = cte.city and prev.date between dateadd(day,-6,cte.date) and dateadd(day,-1,cte.date) and prev.weather = cte.weather ) ca