我对您的目标的理解:
- 计算每月每个 LogicalDeviceName 的事件计数
- 计算每个 LogicalDeviceName 每月事件的中位数
- 计算每个 EVS 每月事件的中位数
我的工作假设是,对于任何给定的 LogicalDeviceName,只有一个匹配的 EVS。例如,当 LogicalDeviceName 值为“Apollo”时,EVS 值将始终为“Commercial”。
请注意,我创建并填充了测试表以获取下面的屏幕截图。脚本包含在下面。
目标 1:汇总每个 LogicalDeviceName 每月的事件计数,以回答“2015 年 1 月 Apollo 发生了多少事件?”之类的问题。像这样的查询应该可以解决问题。将年和月部分与日分开允许月聚合:
SELECT
LogicalDeviceName
, SUM(Events) [ConsolidatedEvents]
, EVS
, FORMAT(StartDate, 'yyyy/MM') [YearAndMonth]
FROM [Test]
GROUP BY
LogicalDeviceName
, EVS
, FORMAT(StartDate, 'yyyy/MM')
ORDER BY
YearAndMonth DESC
, LogicalDeviceName
目标 2:计算每个 LogicalDeviceName 每月事件的中位数
SELECT DISTINCT
LogicalDeviceName
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Events)
OVER (PARTITION BY LogicalDeviceName, YEAR(StartDate), MONTH(StartDate)) [Median]
, FORMAT(StartDate, 'yyyy/MM') [YearAndMonth]
FROM [Test]
ORDER BY [YearAndMonth] DESC, LogicalDeviceName
需要使用 DISTINCT 因为PARTITION BY includes a row for each record。另请注意,虽然这种语法更简单,但 there are potentially more performant ways to calculate median.
目标 3:使用每个 LogicalDeviceName 的事件“合并”(SUM) 计算每个 EVS 每月事件的中位数
这就是我对你想要完成的事情感到有点模糊的地方。如果提供进一步说明,将更新。根据提供的前/后组屏幕截图在下面进行编辑。在我的脑海中,CTE 构建第一个查询是最简单的方法:
WITH Consolidated AS
(
SELECT
LogicalDeviceName
, SUM(Events) [ConsolidatedEvents]
, EVS
, FORMAT(StartDate, 'yyyy/MM') [YearAndMonth]
FROM [Test]
GROUP BY
LogicalDeviceName
, EVS
, FORMAT(StartDate, 'yyyy/MM')
)
SELECT DISTINCT
EVS
, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY ConsolidatedEvents)
OVER (PARTITION BY EVS, YearAndMonth) [Median]
, YearAndMonth
FROM Consolidated
ORDER BY YearAndMonth DESC, EVS
测试表创建/填充脚本:
SET NOCOUNT ON
GO
CREATE TABLE [Test]
(
LogicalDeviceName VARCHAR(64)
, Events INT
, EVS VARCHAR(16)
, StartDate DATETIME2
)
GO
DECLARE @LDN_EVS_Pairs TABLE
(
LDN VARCHAR(16)
, EVS VARCHAR(16)
)
INSERT INTO @LDN_EVS_Pairs(LDN, EVS)
VALUES
('Apollo', 'Commercial')
, ('Appleton1', 'Commercial')
, ('Baptist Beaches', 'Sodexo')
, ('Florida Hospital', 'Commercial')
, ('FROST', 'VA/DoD')
, ('FVAMC1', 'VA/DoD')
, ('GERMN8R', 'Commercial')
, ('Glady', 'Commercial')
, ('Sheldon', 'Sodexo')
DECLARE
@Counter INT = 10000
, @Multiplier INT
, @CurrentLDN VARCHAR(16)
, @CurrentEvents INT
, @CurrentEVS VARCHAR(16)
, @CurrentStartDate DATETIME2
, @MinEvents INT = 0
, @MaxEvents INT = 50
, @MinDate DATE = '20120101'
, @MaxDate DATE = '20200707'
WHILE (@Counter > 0)
BEGIN
SELECT TOP(1)
@Multiplier = ABS(CHECKSUM(NEWID()) % (@MaxEvents/2 - @MinEvents + 1)) + @MinEvents
, @CurrentLDN = LDN
, @CurrentEvents = ABS(CHECKSUM(NEWID()) % (@MaxEvents - @MinEvents + 1)) + @MinEvents
, @CurrentEVS = EVS
, @CurrentStartDate = DATEADD(DAY,ABS(CHECKSUM(NEWID())) % (1+DATEDIFF(DAY,@MinDate,@MaxDate)),@MinDate)
FROM @LDN_EVS_Pairs
ORDER BY NEWID()
WHILE(@Multiplier > 0)
BEGIN
INSERT INTO [Test](LogicalDeviceName, Events, EVS, StartDate)
VALUES(@CurrentLDN, @CurrentEvents, @CurrentEVS, @CurrentStartDate)
SET @Multiplier -= 1
END
SET @Counter -= 1
END
this SO Post 为生成随机值提供了一点帮助。