好的,所以我吮吸SQL ... 如果我在SQL Server(2015+)中有一个 CityName , WeatherProviderName , TimeStamp , TempCelcius 下, 我想要的是每个天气提供商的每个城市的预测,这些预测已在过去 2天内报告, plus 每个 City + 提供商的最新预测,这些预测在过去 2天内未预测任何内容
是否只有一个查询可以获得更高效的信息,只需单独请求2? 我知道我可以得到最新的值(基于this article),如下所示:
select t.CityName, t.WeatherProviderName, t.TimeStamp, t.TempCelcius from Forecasts t
inner join (
select CityName, WeatherProviderName, TempCelcius, max(TimeStamp) as maxTime
from Forecasts where TimeStamp < DATEADD(DAY,-2, GETDATE())
group by CityName, WeatherProviderName
) tm on t.CityName = tm.CityName AND t.WeatherProviderName = tm.WeatherProviderName AND t.TimeStamp = tm.maxTime
(也尝试使用that SO question的分区,但我的测试集的速度慢了3倍)
我可以通过以下方式获取最近2天的所有内容:
select CityName, WeatherProviderName, TimeStamp, TempCelcius from Forecasts where TimeStamp > DATEADD(DAY,-2, GETDATE())
但是不是将它们分别运行到2个集合和组合中,有没有办法在快速的单个查询中同时使用它们?
答案备注
我按照@Forklift(谢谢)的建议去了联盟,在下面的评论中。这是建议的最快选择。它看起来像这样:
SELECT t.CityName, t.WeatherProviderName, t.TimeStamp, t.TempCelcius FROM
Forecasts t
INNER JOIN (
SELECT CityName, WeatherProviderName, TempCelcius, max(TimeStamp) AS maxTime
FROM Forecasts WHERE TimeStamp < DATEADD(DAY,-2, GETDATE())
GROUP BY CityName, WeatherProviderName
) tm ON t.CityName = tm.CityName AND t.WeatherProviderName = tm.WeatherProviderName AND t.TimeStamp = tm.maxTime
UNION
SELECT CityName, WeatherProviderName, TimeStamp, TempCelcius FROM Forecasts WHERE TimeStamp > DATEADD(DAY,-2, GETDATE())
我还将@SqlZsm标记为答案,因为它确实在单个查询中执行...所以根据您的确切需要,您可以使用@Forklift或@SqlZsm来感谢:)
答案 0 :(得分:3)
这将返回过去两天的所有行,以及使用带有 row_number()
的子查询在过去两天内没有行的行的最新行:
select s.CityName, s.WeatherProviderName, s.TimeStamp, s.TempCelcius
from (
select t.CityName, t.WeatherProviderName, t.TimeStamp, t.TempCelcius
, rn = row_number() over (
partition by t.CityName, t.WeatherProviderName
order by t.TimeStamp desc
)
from Forecasts t
) as s
where s.TimeStamp > dateadd(day,-2, getdate())
or rn = 1
rextester演示:http://rextester.com/YQS70477
测试设置:
create table Forecasts (
CityName varchar(32)
, WeatherProviderName varchar(32)
, TimeStamp datetime
, TempCelcius float
)
insert into Forecasts values
('Sierra Leon','CNN','19881230',30)
,('Sierra Leon','CNN','19881231',30)
,('Sierra Leon','BBC','19881231',30)
,('Sierra Leon','BBC',dateadd(day,-2, getdate()),28)
,('Sierra Leon','BBC',dateadd(day,-1, getdate()),29)
,('Sierra Leon','BBC',getdate(),30)
查询:
select s.CityName, s.WeatherProviderName, s.TimeStamp, s.TempCelcius
from (
select t.CityName, t.WeatherProviderName, t.TimeStamp, t.TempCelcius
, rn = row_number() over (
partition by t.CityName, t.WeatherProviderName
order by t.TimeStamp desc
)
from Forecasts t
) as s
where s.TimeStamp > dateadd(day,-2, getdate())
or rn = 1
返回:
+-------------+---------------------+---------------------+-------------+
| CityName | WeatherProviderName | TimeStamp | TempCelcius |
+-------------+---------------------+---------------------+-------------+
| Sierra Leon | BBC | 09.03.2017 19:49:06 | 30 |
| Sierra Leon | BBC | 08.03.2017 19:49:06 | 29 |
| Sierra Leon | CNN | 31.12.1988 00:00:00 | 30 |
+-------------+---------------------+---------------------+-------------+
答案 1 :(得分:0)
你可以试试这个
select CityName, WeatherProviderName, TimeStamp, TempCelcius from Forecasts where TimeStamp > DATEADD(DAY,-2, GETDATE())
union all
select * from (
select CityName, WeatherProviderName, TimeStamp, TempCelcius, row_number() over (partition by concat(CityName, WeatherProviderName) order by TimeStamp desc) as rn from Forecasts where TimeStamp < DATEADD(DAY,-2, GETDATE())
)
where rn = 1