欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解鎖?SQL?Server?2022的時(shí)間序列數(shù)據(jù)功能(示例詳解)

 更新時(shí)間:2024年08月03日 09:04:01   作者:樺仔  
SQL?Server2022在處理時(shí)間序列數(shù)據(jù)時(shí),SQL?Server?提供了一些優(yōu)化和功能,比如?DATE_BUCKET?函數(shù)、窗口函數(shù)以及其他時(shí)間日期函數(shù),以便更高效地處理時(shí)間序列數(shù)據(jù),這篇文章主要介紹了解鎖?SQL?Server?2022的時(shí)間序列數(shù)據(jù)功能,需要的朋友可以參考下

SQL Server2022在處理時(shí)間序列數(shù)據(jù)時(shí),SQL Server 提供了一些優(yōu)化和功能,比如 DATE_BUCKET 函數(shù)、窗口函數(shù)(如 FIRST_VALUE 和 LAST_VALUE)以及其他時(shí)間日期函數(shù),以便更高效地處理時(shí)間序列數(shù)據(jù)。

 GENERATE_SERIES函數(shù)

SQL Server 2022 引入了一個(gè)新的函數(shù) GENERATE_SERIES,它用于生成一個(gè)整數(shù)序列。
這個(gè)函數(shù)非常有用,可以在查詢中生成一系列連續(xù)的數(shù)值,而無(wú)需創(chuàng)建臨時(shí)表或循環(huán)。

GENERATE_SERIES ( start, stop [, step ] )
start:序列的起始值。
stop:序列的終止值。
step:每次遞增或遞減的步長(zhǎng)(可選)。如果省略,默認(rèn)為1。

 使用場(chǎng)景包括快速生成一系列數(shù)據(jù)用于測(cè)試或填充表或者結(jié)合日期函數(shù)生成一系列日期值。

示例

生成的結(jié)果集將包含 20 行,每行顯示從 '2019-02-28 13:45:23' 開(kāi)始,按分鐘遞增的時(shí)間。

SELECT DATEADD(MINUTE, s.value, '2019-02-28 13:45:23') AS [Interval]
FROM GENERATE_SERIES(0, 20, 1) AS s;

對(duì)于每一個(gè) s.value,DATEADD 函數(shù)將基準(zhǔn)日期時(shí)間增加相應(yīng)的分鐘數(shù)。

DATE_BUCKET函數(shù)

SQL Server 2022 引入了一個(gè)新的函數(shù) DATE_BUCKET,用于將日期時(shí)間值按指定的時(shí)間間隔分組(即分桶)。

這個(gè)函數(shù)在時(shí)間序列分析、數(shù)據(jù)聚合和分段分析等場(chǎng)景中非常有用。

DATE_BUCKET ( bucket_width, datepart, startdate, date )
bucket_width:時(shí)間間隔的大小,可以是整數(shù)。
datepart:時(shí)間間隔的類型,例如 year, month, day, hour, minute, second 等。
startdate:起始日期,用于定義時(shí)間間隔的起點(diǎn)。
date:需要分組的日期時(shí)間值。

使用 DATE_BUCKET 函數(shù)時(shí),指定的時(shí)間間隔單位(如 YEAR、QUARTER、MONTH、WEEK 等)以及起始日期(origin)決定了日期時(shí)間值被分配到哪個(gè)存儲(chǔ)桶。這種方式有助于理解時(shí)間間隔的計(jì)算是如何基于起始日期來(lái)進(jìn)行的。

示例

DECLARE @date DATETIME = '2019-09-28 13:45:23';
DECLARE @origin DATETIME = '2019-01-28 13:45:23';
SELECT 'Now' AS [BucketName], @date AS [DateBucketValue]
UNION ALL
SELECT 'Year', DATE_BUCKET (YEAR, 1, @date, @origin)
UNION ALL
SELECT 'Quarter', DATE_BUCKET (QUARTER, 1, @date, @origin)
UNION ALL
SELECT 'Month', DATE_BUCKET (MONTH, 1, @date, @origin)
UNION ALL
SELECT 'Week', DATE_BUCKET (WEEK, 1, @date, @origin)
--假如日期時(shí)間值如下:
Now: 2019-09-28 13:45:23
--按年分組:
DATE_BUCKET(YEAR, 1, @date, @origin)
從 2019-01-28 13:45:23 開(kāi)始的年度存儲(chǔ)桶,2019-09-28 落入 2019-01-28 至 2020-01-28 的存儲(chǔ)桶中。
結(jié)果:2019-01-28 13:45:23
--按季度分組:
DATE_BUCKET(QUARTER, 1, @date, @origin)
從 2019-01-28 13:45:23 開(kāi)始的季度存儲(chǔ)桶,每個(gè)季度 3 個(gè)月。
2019-09-28 落入第三個(gè)季度存儲(chǔ)桶(即從 2019-07-28 13:45:23 到 2019-10-28 13:45:23)。
結(jié)果:2019-07-28 13:45:23
--按月分組:
DATE_BUCKET(MONTH, 1, @date, @origin)
從 2019-01-28 13:45:23 開(kāi)始的月度存儲(chǔ)桶,每個(gè)月一個(gè)存儲(chǔ)桶。
2019-09-28 落入第九個(gè)存儲(chǔ)桶(即從 2019-09-28 13:45:23 到 2019-10-28 13:45:23)。
結(jié)果:2019-09-28 13:45:23
--按周分組:
DATE_BUCKET(WEEK, 1, @date, @origin)
從 2019-01-28 13:45:23 開(kāi)始的每周存儲(chǔ)桶。
2019-09-28 落入從 2019-09-23 13:45:23 到 2019-09-30 13:45:23 的存儲(chǔ)桶。
結(jié)果:2019-09-23 13:45:23

SELECT 'Now' AS [BucketName], GETDATE() AS [BucketDate]
UNION ALL
SELECT '5 Minute Buckets', DATE_BUCKET (MINUTE, 5, GETDATE())
UNION ALL
SELECT 'Quarter Hour', DATE_BUCKET (MINUTE, 15, GETDATE());
Now:
BucketName: Now
BucketDate: 2024-07-26 16:14:11.030
這是當(dāng)前時(shí)間,即 GETDATE() 返回的系統(tǒng)當(dāng)前時(shí)間。
5 Minute Buckets:
BucketName: 5 Minute Buckets
BucketDate: 2024-07-26 16:10:00.000
這是將當(dāng)前時(shí)間按 5 分鐘間隔進(jìn)行分組的結(jié)果。DATE_BUCKET(MINUTE, 5, GETDATE()) 返回當(dāng)前時(shí)間所在的 5 分鐘區(qū)間的起始時(shí)間。在這個(gè)例子中,16:14:11 落在 16:10:00 到 16:15:00 之間,因此返回 16:10:00。
Quarter Hour:
BucketName: Quarter Hour
BucketDate: 2024-07-26 16:00:00.000
這是將當(dāng)前時(shí)間按 15 分鐘間隔進(jìn)行分組的結(jié)果。DATE_BUCKET(MINUTE, 15, GETDATE()) 返回當(dāng)前時(shí)間所在的 15 分鐘區(qū)間的起始時(shí)間。在這個(gè)例子中,16:14:11 落在 16:00:00 到 16:15:00 之間,因此返回 16:00:00。

更多實(shí)際場(chǎng)景示例

按自定義起始日期分組
假設(shè)我們有一系列事件時(shí)間 EventTime,希望從'2023-01-01'日期開(kāi)始,每周進(jìn)行分組統(tǒng)計(jì)事件數(shù)量。

--創(chuàng)建表 Events:
USE [testdb]
GO
CREATE TABLE Events (
    EventID INT PRIMARY KEY,
    EventTime DATETIME
);
INSERT INTO Events (EventID, EventTime) VALUES
(1, '2023-01-02 14:30:00'),
(2, '2023-01-08 09:15:00'),
(3, '2023-01-09 17:45:00'),
(4, '2023-01-15 12:00:00'),
(5, '2023-01-16 08:00:00'),
(6, '2023-01-22 19:30:00'),
(7, '2023-01-29 11:00:00');
--從'2023-01-01'起始日期開(kāi)始,每周進(jìn)行分組統(tǒng)計(jì)事件數(shù)量。
DECLARE @origin DATETIME = '2023-01-01';
SELECT
    DATE_BUCKET(WEEK, 1, EventTime, @origin) AS WeekStart,
    COUNT(*) AS EventCount
FROM
    Events
GROUP BY
    DATE_BUCKET(WEEK, 1, EventTime, @origin)
ORDER BY
    WeekStart;

按自定義時(shí)間間隔分組
假設(shè)我們有一個(gè)傳感器數(shù)據(jù)表 SensorReadings

USE [testdb]
GO
CREATE TABLE SensorReadings (
    ReadingID INT PRIMARY KEY,  --唯一標(biāo)識(shí)
    ReadingTime DATETIME,  --讀數(shù)的時(shí)間
    Value FLOAT  --讀數(shù)的值
);
INSERT INTO SensorReadings (ReadingID, ReadingTime, Value) VALUES
(1, '2023-07-26 10:03:00', 23.5),
(2, '2023-07-26 10:05:00', 24.1),
(3, '2023-07-26 10:09:00', 22.8),
(4, '2023-07-26 10:15:00', 25.0),
(5, '2023-07-26 10:20:00', 23.9),
(6, '2023-07-26 10:27:00', 24.3),
(7, '2023-07-26 10:29:00', 24.5);
--我們希望按 10 分鐘的間隔將數(shù)據(jù)分組,并計(jì)算每個(gè)間隔的平均讀數(shù)值。
SELECT
    DATE_BUCKET(MINUTE, 10, ReadingTime) AS BucketStartTime,
    ROUND(AVG(Value),4) AS AverageValue
FROM
    SensorReadings
GROUP BY
    DATE_BUCKET(MINUTE, 10, ReadingTime)
ORDER BY
    BucketStartTime;

如果是傳統(tǒng)方法需要使用公用表表達(dá)式CTE才能完成這個(gè)需求

--查詢:按 10 分鐘間隔分組并計(jì)算平均值
WITH TimeIntervals AS (
    SELECT
        ReadingID,
        ReadingTime,
        Value,
        --將分鐘數(shù)歸約到最近的 10 分鐘的整數(shù)倍, 從2010年到現(xiàn)在有多少個(gè)10分鐘區(qū)間
        DATEADD(MINUTE, (DATEDIFF(MINUTE, '2000-01-01', ReadingTime) / 10) * 10, '2010-01-01') AS BucketStartTime  
    FROM
        SensorReadings
)
SELECT
    BucketStartTime,
    ROUND(AVG(Value), 4) AS AverageValue
FROM
    TimeIntervals
GROUP BY
    BucketStartTime
ORDER BY
    BucketStartTime;

WITH TimeIntervals AS (...)公共表表達(dá)式(CTE)用于計(jì)算每條記錄的 BucketStartTime。
DATEDIFF(MINUTE, '2000-01-01', ReadingTime) / 10 計(jì)算 ReadingTime 到基準(zhǔn)時(shí)間 '2000-01-01' 的分鐘數(shù),然后除以 10,得到當(dāng)前時(shí)間點(diǎn)所在的 10 分鐘區(qū)間的索引。
DATEADD(MINUTE, ..., '2000-01-01') 將該索引轉(zhuǎn)換回具體的時(shí)間點(diǎn),即區(qū)間的起始時(shí)間。

查詢主部分:
選擇 BucketStartTime 和相應(yīng)區(qū)間內(nèi)讀數(shù)值的平均值。
使用 GROUP BY 按 BucketStartTime 分組,并計(jì)算每個(gè)分組的平均值。
ORDER BY 用于按照時(shí)間順序排列結(jié)果。

FIRST_VALUE 和 LAST_VALUE 窗口函數(shù)

在 之前版本的SQL Server 中,F(xiàn)IRST_VALUE 和 LAST_VALUE 是窗口函數(shù),用于在一個(gè)分區(qū)或窗口中返回第一個(gè)或最后一個(gè)值。

SQL Server 2022 引入了新的選項(xiàng) IGNORE NULLS 和 RESPECT NULLS 來(lái)處理空值(NULL)的方式,從而增強(qiáng)了這些函數(shù)的功能。

基本語(yǔ)法

FIRST_VALUE
返回指定窗口或分區(qū)中按指定順序的第一個(gè)值。
FIRST_VALUE ( [scalar_expression ] ) 
OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )
LAST_VALUE
返回指定窗口或分區(qū)中按指定順序的最后一個(gè)值。
LAST_VALUE ( [scalar_expression ] ) 
OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )
新功能:IGNORE NULLS 和 RESPECT NULLS
IGNORE NULLS: 忽略分區(qū)或窗口中的 NULL 值。
RESPECT NULLS: 默認(rèn)行為,包含分區(qū)或窗口中的 NULL 值。

示例

假設(shè)我們有一個(gè)表 MachineTelemetry,包含以下數(shù)據(jù):

CREATE TABLE MachineTelemetry (
    [timestamp] DATETIME,
    SensorReading FLOAT
);
INSERT INTO MachineTelemetry ([timestamp], SensorReading) VALUES
('2023-07-26 10:00:00', 23.5),
('2023-07-26 10:00:15', 24.1),
('2023-07-26 10:00:30', NULL),
('2023-07-26 10:00:45', 25.0),
('2023-07-26 10:01:00', NULL),
('2023-07-26 10:01:15', 23.9),
('2023-07-26 10:01:30', NULL),
('2023-07-26 10:01:45', 24.3);

默認(rèn)行為(包含 NULL 值)

--使用 FIRST_VALUE 和 LAST_VALUE 進(jìn)行差距分析
--默認(rèn)行為(包含 NULL 值)
SELECT 
    [timestamp],
    DATE_BUCKET(MINUTE, 1, [timestamp]) AS [timestamp_bucket],
    SensorReading,
    FIRST_VALUE(SensorReading) OVER (
        PARTITION BY DATE_BUCKET(MINUTE, 1, [timestamp]) 
        ORDER BY [timestamp] 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS [Default_FIRST_VALUE (RESPECT NULLS)],
    LAST_VALUE(SensorReading) OVER (
        PARTITION BY DATE_BUCKET(MINUTE, 1, [timestamp]) 
        ORDER BY [timestamp] 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS [Default_LAST_VALUE (RESPECT NULLS)]
FROM MachineTelemetry
ORDER BY [timestamp];

忽略 NULL 值

--忽略 NULL 值
SELECT 
    [timestamp],
    DATE_BUCKET(MINUTE, 1, [timestamp]) AS [timestamp_bucket],
    SensorReading,
    FIRST_VALUE(SensorReading) IGNORE NULLS OVER (
        PARTITION BY DATE_BUCKET(MINUTE, 1, [timestamp]) 
        ORDER BY [timestamp] 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS [First_Reading (IGNORE NULLS)],
    LAST_VALUE(SensorReading) IGNORE NULLS OVER (
        PARTITION BY DATE_BUCKET(MINUTE, 1, [timestamp]) 
        ORDER BY [timestamp] 
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    ) AS [Last_Reading (IGNORE NULLS)]
FROM MachineTelemetry
ORDER BY [timestamp];

 總結(jié)

實(shí)際上,對(duì)于時(shí)間序列我們一般使用專業(yè)的時(shí)間序列數(shù)據(jù)庫(kù),例如InfluxDB 。

它使用 TSM(Time-Structured Merge Tree)作為存儲(chǔ)引擎稱,這是 LSM 樹的一種變體,專門優(yōu)化用于時(shí)間序列數(shù)據(jù)的寫入和查詢性能。

另外,SQL Server 的時(shí)間序列功能是使用行存儲(chǔ)引擎(Row Store)作為其存儲(chǔ)引擎,這意味著數(shù)據(jù)是按行進(jìn)行存儲(chǔ)和處理的。

在大部分場(chǎng)景下面,如果性能不是要求非常高,其實(shí)SQL Server 存儲(chǔ)時(shí)間序列數(shù)據(jù)性能是完全足夠的,而且額外使用InfluxDB數(shù)據(jù)庫(kù)需要維護(hù)多一個(gè)技術(shù)棧,對(duì)運(yùn)維要求更加高。

特別是現(xiàn)在追求數(shù)據(jù)庫(kù)一體化的趨勢(shì)背景下,無(wú)論是時(shí)間序列數(shù)據(jù),向量數(shù)據(jù),地理數(shù)據(jù),json數(shù)據(jù)都最好在一個(gè)數(shù)據(jù)庫(kù)里全部滿足,減輕運(yùn)維負(fù)擔(dān),復(fù)用技術(shù)棧,減少重復(fù)建設(shè)成本是比較好的解決方案。

參考文章

https://sqlbits.com/sessions/event2024/Time_Series_with_SQL_Server_2022

https://www.microsoft.com/en-us/sql-server/blog/2023/01/12/working-with-time-series-data-in-sql-server-2022-and-azure-sql/

https://www.mssqltips.com/sqlservertip/6232/load-time-series-data-with-sql-server/

到此這篇關(guān)于解鎖 SQL Server 2022的時(shí)間序列數(shù)據(jù)功能的文章就介紹到這了,更多相關(guān)SQL Server 2022時(shí)間序列數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論