查看填补 SQL 中的时间间隙

问题描述 投票:0回答:1

因此,我正在致力于将数据加载到一个平台上,该平台只能以小时粒度或日粒度可视化数据。我向他们提供了到我的数据库的连接字符串,该系统从中提取数据并将其显示为图表,并执行一系列切片和切块操作。问题是它基于图表的可视化仅适用于小时或日粒度,而我的数据是每 4 小时一次。它认为这是缺失数据,并且图表显示为点而不是连续线。所以我想到公开一个视图,它可以用最后使用的数据按小时粒度填充数据,并且平台可以使用它。这带来了一些问题。顺便说一句,我不是 SQL 专家。

数据库模式:record_date、segment_key、segment_value、avg_conspiration、avg_charge ...(更多数字列)

每个segment_key、segment_value组合每4小时更新一次,我能够按照本指南形成一个查询来填充间隙填充时间间隙并估算缺失值

但是这是一个使用临时表作为解决方案的查询,而不是视图,原始表可能包含几年的大量数据,这可能会导致性能不佳。此外,临时表的开始/结束时间不能进行硬编码,因为这是滚动数据。

有没有一种更优雅的方法可以在不使用任何连接的情况下填充间隙。如果使用连接它仍然是高性能的。

按照[Microsoft网站]的指南尝试查询(填充时间间隙并估算缺失值 )。但它会在填充和公开之前从表中读取所有数据。

sql sql-server azure-sql-database
1个回答
0
投票

在 Azure SQL 数据库中,使用

GENERATE_SERIES
生成一系列日期或时间非常容易。您可以根据所需的时间间隔创建表值函数而不是视图,并传入开始/结束日期。这个可以处理几天或几小时,并且可以很容易地扩展到处理几分钟、几周、几个月等:

CREATE OR ALTER FUNCTION dbo.GetInterval
(
  @part  varchar(4), 
  @start date, 
  @end   date
)
RETURNS TABLE WITH SCHEMABINDING
AS
  RETURN 
  (
    SELECT period_start = s, 
           period_end   = CASE @part
              WHEN 'day'  THEN DATEADD(DAY,  1, s) 
              WHEN 'hour' THEN DATEADD(HOUR, 1, s) 
           END
      FROM
      (
        SELECT s = DATEADD(HOUR, Value-1, CONVERT(datetime, @start))
          FROM GENERATE_SERIES(1, DATEDIFF(HOUR, @start, @end))
         WHERE @part = 'hour'

        UNION ALL

        SELECT s = DATEADD(DAY, Value-1, @start)
          FROM GENERATE_SERIES(1, DATEDIFF(DAY, @start, @end))
         WHERE @part = 'day'
    ) AS x
  );

然后针对该函数查询完整的日期列表,并外连接到您的实际数据,例如(你没有提供任何模式或数据,所以只是编造的东西):

SELECT tp.period_start, 
       sales = COALESCE(SUM(s.sales), 0)
  FROM dbo.GetInterval('day', @start, @end) AS tp
  LEFT OUTER JOIN dbo.Sales AS s
    ON s.sale_datetime >= s.period_start
   AND s.sale_datetime <  s.period_end
 GROUP BY tp.period_start
 ORDER BY tp.period_start;

如果性能不佳,可能是因为基础表没有正确索引以支持范围查询;这不会是因为您加入了太多日期/时间。或者性能问题根本不是连接,而只是试图返回/渲染太多行。如果您获得三个月的分钟间隔并对 400 个产品进行聚合,那么,要返回的数据量很大(超过 5000 万行)。

© www.soinside.com 2019 - 2024. All rights reserved.