Это соответствует вашим требованиям. Измените значение параметра @op
на MIN, MAX или AVG, а параметр @Group
на размер группы.
Функция ранжирования NTILE
используется для разделения групп, затем ROW_NUMBER
для идентификации первого / последнего члена каждой группы.
DECLARE @t TABLE
(id INT,
VALUE REAL
)
INSERT @t (id,VALUE)
VALUES
(1, 6.7),
(2, 8.9),
(3, 4.5),
(5, 3.2),
(8, 2.5),
(9, 2.1),
(10, 1.0),
(15, 2.3),
(18, 2.4),
(19, 4.0),
(20, 3.2)
DECLARE @Group DECIMAL(5,1) = 3.0
DECLARE @Bucket INT
DECLARE @op char(3) = 'MIN' --MAX, AVG
SELECT @Bucket = CEILING(COUNT(1)/@Group)
FROM @t
;WITH bucketCTE
AS
(
SELECT *,NTILE(@Bucket) OVER (ORDER BY id) bucket
FROM @t
)
,rankCTE
AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY bucket
ORDER BY id ASC
) AS rn,
ROW_NUMBER() OVER (PARTITION BY bucket
ORDER BY id DESC
) AS rn2
FROM bucketCTE
)
,groupCTE
AS
(
SELECT AVG(VALUE) average, MIN(VALUE) minimum, MAX(VALUE) maximum, bucket
FROM bucketCTE
GROUP BY bucket
)
SELECT r1.id minId, r2.id maxId , CASE WHEN @op = 'AVG' THEN g.average
WHEN @op = 'MIN' THEN g.minimum
WHEN @op = 'MAX' THEN g.maximum
ELSE NULL
END AS value
FROM rankCTE AS r1
JOIN rankCTE AS r2
ON r2.bucket = r1.bucket
AND r2.rn2 = 1
JOIN groupCTE AS g
ON g.bucket = r1.bucket
WHERE r1.rn = 1
ORDER BY r1.bucket