sql - 如何在单个 SQL 查询中获取最新日期和日期以来的所有内容

标签 sql sql-server t-sql

好吧,我对 SQL 很烂... 如果我在 SQL Server (2015+) 中有一个表 Forecasts,其中包含 CityNameWeatherProviderNameTimeStamp、<强>摄氏温度, 我想要从中得到的是过去2天报告的每个天气提供商对每个城市的天气预报,加上每个城市的最新预报+过去2天内未进行任何预报的提供商 em>.

是否有一个查询可以比单独请求两个查询的性能更高? 我知道我可以获得最新值(基于 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 :)

最佳答案

这将返回过去两天的所有行,以及使用带有 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 |
+-------------+---------------------+---------------------+-------------+

关于sql - 如何在单个 SQL 查询中获取最新日期和日期以来的所有内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42702643/

相关文章:

c# - T-SQL:ASP.NET GridView 中选定列的动态查询

sql - 不同的值对 SQL

sql - 无法通过 IP 和命名实例远程连接到 SQL 2012

sql-server - SQL Server - 使用 UNPIVOT 包含 NULL

sql - 搜索已包含通配符的 SQL 表?

c# - 如何从 t-sql 过程传递警告消息?

sql-server - 哈希函数-sql studio Express

mysql - 在 mysql 表中查找 id 不唯一的漏洞

mysql - 如何在查询后合并字段,我知道 CONCAT,但不是这种方式

mysql - 使用不同的日期字段排序