Вы действительно не хотите пытаться сделать это для сводных данных, и, хотя вы заявляете, что данные не хранятся таким образом, вы не показали нам, как вы попали в сводные города в виде столбцов -Это позор.
Итак, я «отменил» выборку в общем табличном выражении, а затем использовал apply operator
для подсчета предыдущих явлений той же погоды за 5 предыдущих дней.Похоже, вы знаете, как выполнить поворот. Я оставляю вам возможность затем изменить окончательный результат.
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, <b>datediff(day,ca.prior,cte.date)</b> as prior
from cte
cross apply (
select <b>min(prev.date)</b> 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