Этот сценарий похож на SQL: количество строк с момента появления определенного значения
В SQL Server я пытаюсь рассчитать количество дней с той же погоды, что исегодня (предположим, что сегодня 6 августа 2018 года) наблюдалось впервые за последние 5 дней.По городам.
Вот данные:
+---------+---------+--------+--------+--------+
| 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 дней было 3 августа.
Но я хочу получить следующую таблицу:
+---------+-------+--------+--------+
| Toronto | Cairo | Zagreb | Ankara |
+---------+-------+--------+--------+
| 4 | 5 | 1 | 5 |
+---------+-------+--------+--------+
Слегка изменен из принятого ответа @Used_By_. Уже этот код:
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');
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, datediff(day,ca.prior,cte.date)+1 as daysPresent
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,-4,cte.date) and dateadd(day,0,cte.date)
and prev.weather = cte.weather
) ca
order by city,date
Вывод:
Однако сейчас я пытаюсь продолжать считать «daysPresent» даже после этих пятипрошедшие дни под вопросом.Это означает, что последняя отмеченная строка в выходной выборке должна показывать 6. Логика заключается в том, чтобы увеличить предыдущее число на количество дней между ними, если между ними меньше 5 дней.Если за последние 5 дней не было такой же погоды, вернитесь к 1.
Я экспериментировал с LEAD и LAG, но не могу заставить его работать.Это даже правильный способ добавить еще один слой к нему, или запрос должен выглядеть совсем иначе?
Я просто озадачен.