Suppose I have the following table in my SQL Server (2012) DB:
Tbl1:
Id1: Id2: Date: Value:
1 A '2018-01-01' 1
1 B '2018-01-01' 1
1 C '2018-01-01' 1
1 A '2018-01-02' 1
1 B '2018-01-02' 1
1 A '2018-01-31' 1
And I want to get the average of Value
per Id2
where Id1 = 1
for Date BETWEEN '2018-01-01' AND '2018-01-02'
.
HOWEVER, for the average, I want to divide by the total number of Date
s available, NOT JUST FOR THAT ONE Id2
.
So, my resultset would be:
Id2: AvgVal:
A 1+1 / 2 = 1
B 1+1 / 2 = 1
C 1 / 2 = 0.5
Note that C's value is divided by 2 even though there is only 1 value for C in that date range (in other words, we're dividing by COUNT(DISTINCT Date) OVER (PARTITION BY Id1)
only. Not the extra grouping by Id2
.
I've come up with a way to do it using CTEs and can think of a way to do it by storing the divisor in a temporary variable, but I'm REALLY trying to think through if there's a way to accomplish this in a single SELECT statement.
My current solution looks as follows:
DECLARE @StartDate DATE = '2018-01-01', @EndDate DATE = '2018-01-02', @Id1 INT = 1;
DECLARE @Tbl1 TABLE ([Id1] INT, [Id2] VARCHAR(1), [Date] DATE, [Value] FLOAT);
INSERT INTO @Tbl1 (Id1, Id2, Date, Value)
VALUES
(1, 'A','2018-01-01', 1),
(1, 'B','2018-01-01', 1),
(1, 'C','2018-01-01', 1),
(1, 'A','2018-01-02', 1),
(1, 'B','2018-01-02', 1),
(1, 'A','2018-01-31', 1)
;
WITH CTE AS
(
SELECT *
FROM @Tbl1
WHERE [Date] BETWEEN @StartDate AND @EndDate
AND Id1 = @Id1
),
CTE1 AS
(
SELECT COUNT(DISTINCT [Date]) AS MaxNumDates FROM CTE
)
SELECT
Id2
,SUM(Value) / MaxNumDates AS AvgVal
FROM
CTE
JOIN CTE1
ON 1 = 1
GROUP BY
Id2,
MaxNumDates
And, like I said, I figure I could also do it by assigning a local variable to the value of MaxNumDates
, but I'm really trying to see if there's a way to do this via a single query with some form of partitioning / aggregation - Assuming, of course, it is a better way to do it.
Any thoughts?
Thanks!