我有一个表格,其中有一列表示每行插入表格的日期和时间。我正在尝试获取插入的平均和峰值速率的统计数据:
我可以设想一个解决方案,使用GROUP BY
将数据放入“桶”(每个间隔一个),然后平均每个区域中的项目数,但这似乎是一个非常笨重的解决方案。
这个问题是否有更优雅的T-SQL解决方案?
答案 0 :(得分:4)
分组集是要走的路,它们适用于在一个查询中通过多组分组属性(分组集)进行分组的应用程序,并且应该会产生更好的执行计划即更好的表现:
-- if you weren't grouping by minutes and seconds this would
-- probably look more 'elegant'
SELECT
GROUPING_ID(
YEAR(orderdate),
MONTH(orderdate),
DAY(orderdate),
DATEPART(hour, orderdate),
DATEPART(MINUTE, orderdate),
DATEPART(SECOND, orderdate)) AS grp_id,
MAX([Insertions]) AS max_insertions,
AVG([Average]) AS avg_insertions,
YEAR(orderdate) AS order_year,
MONTH(orderdate) AS order_month,
DAY(orderdate) AS order_day,
DATEPART(HOUR, orderdate) AS order_hour,
DATEPART(MINUTE, orderdate) AS order_minute,
DATEPART(SECOND, orderdate) AS order_second -- this will be null if the grouping set is minute
FROM Sales.Orders
GROUP BY
GROUPING SETS
(
(
-- grouping set 1: order second
YEAR(orderdate),
MONTH(orderdate),
DAY(orderdate),
DATEPART(hour, orderdate),
DATEPART(MINUTE, orderdate),
DATEPART(SECOND, orderdate)
),
(
-- grouping set 2: order minute
YEAR(orderdate),
MONTH(orderdate),
DAY(orderdate),
DATEPART(hour, orderdate),
DATEPART(MINUTE, orderdate)
)
);
答案 1 :(得分:2)
GROUP BY
是要走的路。
我会为你想要的每个时间间隔制作一个CTE
,并为每个时间间隔选择最大值:
;WITH CTEMinute AS
(
SELECT YEAR(datefield) yr,
MONTH(datefield) mo,
DAY(datefield) d,
DATEPART(hour, datefield) hr,
DATEPART(minute, datefield) Mint,
COUNT(*) as 'Inserts'
FROM MyTable
GROUP BY YEAR(datefield),
MONTH(datefield),
DAY(datefield),
DATEPART(hour, datefield),
DATEPART(minute, datefield)
)
,CTESecond AS
(
SELECT YEAR(datefield) yr,
MONTH(datefield) mo,
DAY(datefield) d,
DATEPART(hour, datefield) hr,
DATEPART(minute, datefield) Mint,
DATEPART(second, datefield) sec,
COUNT(*) as 'Inserts'
FROM MyTable
GROUP BY YEAR(datefield),
MONTH(datefield),
DAY(datefield),
DATEPART(hour, datefield),
DATEPART(minute, datefield),
DATEPART(second, datefield)
)
然后您可以从CTE
中选择以获得每个时间单位的最大/最小/平均值。
如果您希望它更优雅,您可以在CTE
上制作您可能想要的精细粒度(即毫秒或其他),然后您可以SELECT
/ { {1}}那个。
这样做的问题是GROUP BY
并没有真正表现得那么好,因为它们基本上是没有索引或任何东西的一次性视图,因此在另一个查询中聚合CTE会很快陷入困境。
答案 2 :(得分:2)
扩展J Coopers的回答,我认为Rollup功能可能就是你所追求的。
SELECT
MAX([Insertions]) AS max_insertions,
AVG([Average]) AS avg_insertions,
YEAR(orderdate), AS YEAR
MONTH(orderdate), AS MONTH
DAY(orderdate), AS DAY
DATEPART(hour, orderdate), AS HOUR
DATEPART(MINUTE, orderdate), AS MINUTE
DATEPART(SECOND, orderdate) AS SECOND
FROM Sales.Orders
GROUP BY ROLLUP(
YEAR(orderdate),
MONTH(orderdate),
DAY(orderdate),
DATEPART(hour, orderdate),
DATEPART(MINUTE, orderdate),
DATEPART(SECOND, orderdate)
)