[英]SQL Server - Aggregate by number of records returned for all groups
假设我的 SQL Server 2012 数据库中有下表:
我的表:
DateCol FkId Sector Value
--------------------------------------------
2018-01-01 1 A 1
2018-01-02 1 A 2
2018-01-03 1 A 3
2018-01-04 1 A 4
2018-01-01 1 B 1
2018-01-04 1 B 4
2018-01-01 1 C 1
2018-01-03 1 C 3
2018-01-04 1 C 4
2018-01-01 2 A 1
...
我想获得特定FkId
每个扇区的FkId
,但基于该FkId
总共可用的日期总数。 也就是说,如果我想获得的平均FkId
= 1的日期,比如, 2018-01-01
和2018-01-10
我的结果集将是:
Sector AvgVal
---------------------------------
A (1+2+3+4) / 4 = 2.5
B (1+4) / 4 = 1.25
C (1+3+4) / 4 = 2
换句话说,不是除以该扇区的可用日期数,而是除以该FkId
该日期范围的表中的日期FkId
。
我想我可以通过以下方式使用 CTE 做到这一点:
DECLARE @FkId INT = 1,
@StartDate DATE = '2018-01-01',
@EndDate DATE = '2018-01-10'
DECLARE @MyTable TABLE
(
DateCol DATE,
FkId INT,
Sector VARCHAR(1),
Value FLOAT
);
INSERT INTO @MyTable (DateCol, FkId, Sector, Value)
VALUES
('2018-01-01', 1, 'A', 1),
('2018-01-02', 1, 'A', 2),
('2018-01-03', 1, 'A', 3),
('2018-01-04', 1, 'A', 4),
('2018-01-01', 1, 'B', 1),
('2018-01-04', 1, 'B', 4),
('2018-01-01', 1, 'C', 1),
('2018-01-03', 1, 'C', 3),
('2018-01-04', 1, 'C', 4),
('2018-01-01', 2, 'A', 1);
WITH NumDates AS
(
SELECT
Sector,
COUNT(DateCol) AS cnt
FROM
@MyTable
WHERE
DateCol BETWEEN @StartDate AND @EndDate
AND FkId = @FkId
GROUP BY
Sector
),
MaxNumDates AS
(
SELECT
MAX(cnt) AS MaxNum
FROM
NumDates
)
SELECT
Sector,
SUM(Value) / MaxNum AS AvgVal
FROM
@MyTable
JOIN
MaxNumDates ON 1 = 1
WHERE
DateCol BETWEEN @StartDate AND @EndDate
AND FkId = @FkId
GROUP BY
Sector, MaxNum
但我真的希望有更好的方法。 有什么想法吗?
尝试这个:
select dateCol,
fkid,
sector,
sum(value) over (partition by fkid, sector) /
(select count(distinct dateCol) from @MyTable where fkid = t.fkid)
from @MyTable t
或者
select fkid,
sector,
sum(value) /
(select count(distinct dateCol) from @MyTable where fkid = t.fkid)
from @MyTable t
group by fkid, sector
那是你需要的吗:
DECLARE
@MyTable TABLE
(
DateCol DATE
,FkId INT
,Sector VARCHAR(1)
,Value FLOAT
);
INSERT INTO @MyTable (DateCol, FkId, Sector, Value) VALUES
('2018-01-01', 1, 'A', 1),
('2018-01-02', 1, 'A', 2),
('2018-01-03', 1, 'A', 3),
('2018-01-04', 1, 'A', 4),
('2018-01-01', 1, 'B', 1),
('2018-01-04', 1, 'B', 4),
('2018-01-01', 1, 'C', 1),
('2018-01-03', 1, 'C', 3),
('2018-01-04', 1, 'C', 4),
('2018-01-01', 2, 'A', 1);
SELECT *,
SUM(Value) OVER (PARTITION BY Sector ORDER BY Sector ASC) /
(SELECT COUNT(DISTINCT DateCol) FROM @MyTable WHERE Fkid = Tbl.Fkid) AS Result
FROM @MyTable AS Tbl;
结果:
+---------------------+------+--------+-------+--------+
| DateCol | FkId | Sector | Value | Result |
+---------------------+------+--------+-------+--------+
| 01.01.2018 00:00:00 | 1 | A | 1 | 2,75 |
| 02.01.2018 00:00:00 | 1 | A | 2 | 2,75 |
| 03.01.2018 00:00:00 | 1 | A | 3 | 2,75 |
| 04.01.2018 00:00:00 | 1 | A | 4 | 2,75 |
| 01.01.2018 00:00:00 | 2 | A | 1 | 11 |
| 01.01.2018 00:00:00 | 1 | B | 1 | 1,25 |
| 04.01.2018 00:00:00 | 1 | B | 4 | 1,25 |
| 01.01.2018 00:00:00 | 1 | C | 1 | 2 |
| 03.01.2018 00:00:00 | 1 | C | 3 | 2 |
| 04.01.2018 00:00:00 | 1 | C | 4 | 2 |
+---------------------+------+--------+-------+--------+
select *,
avg_val = AVG([Value]) over
(
partition by Sector, FkId
order by DateCol
range between unbounded preceding and unbounded following
)
from @MyTable;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.