在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())
...由于今天有雨,并且在过去5天内第一次下雨是8月3日,因此正确返回4。
但是我想要返回的是一个像这样的表:
+---------+-------+--------+--------+
| Toronto | Cairo | Zagreb | Ankara |
+---------+-------+--------+--------+
| 4 | 5 | 1 | 5 |
+---------+-------+--------+--------+
这怎么可能?
答案 0 :(得分:2)
您真的不想尝试对数据透视表执行此操作,尽管您声明数据不是以这种方式存储的,但您没有向我们展示如何以列为中心到达城市的透视图-真可惜。
因此,我已在一个公用表表达式中“取消透视”该样本,然后使用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, 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
答案 1 :(得分:1)
我想你想要类似的东西
CREATE TABLE T
(
[Date] DATE,
Toronto VARCHAR(45),
Cairo VARCHAR(45),
Zagreb VARCHAR(45),
Ankara VARCHAR(45)
);
INSERT INTO T VALUES
('2018-08-01', 'Rain', 'Sun', 'Clouds', 'Sun'),
('2018-08-02', 'Sun', 'Sun', 'Clouds', 'Sun'),
('2018-08-03', 'Rain', 'Sun', 'Clouds', 'Rain'),
('2018-08-04', 'Clouds', 'Sun', 'Clouds', 'Clouds'),
('2018-08-05', 'Rain', 'Clouds', 'Rain', 'Rain'),
('2018-08-06', 'Rain', 'Sun', 'Sun', 'Sun');
SELECT
(SELECT MAX(Occ) FROM (SELECT COUNT(Toronto) Occ FROM T WHERE Toronto = (select top 1 toronto from t order by date desc) GROUP BY Toronto) T) Toronto,
(SELECT MAX(Occ) FROM (SELECT COUNT(Cairo) Occ FROM T WHERE Cairo = (select top 1 Cairo from t order by date desc) GROUP BY Cairo) T) Cairo,
(SELECT MAX(Occ) FROM (SELECT COUNT(Zagreb) Occ FROM T WHERE Zagreb = (select top 1 Zagreb from t order by date desc)GROUP BY Zagreb) T) Zagreb,
(SELECT MAX(Occ) FROM (SELECT COUNT(Ankara) Occ FROM T WHERE Ankara = (select top 1 Ankara from t order by date desc)GROUP BY Ankara) T) Ankara
返回
+----+---------+-------+--------+--------+
| | Toronto | Cairo | Zagreb | Ankara |
+----+---------+-------+--------+--------+
| 1 | 4 | 5 | 1 | 3 |
+----+---------+-------+--------+--------+