SQL Server - считать различный вне группы - PullRequest
0 голосов
/ 28 августа 2018

Предположим, у меня есть следующая таблица в моей базе данных SQL Server (2012):

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

И я хочу получить среднее значение Value за Id2, где Id1 = 1 для Date BETWEEN '2018-01-01' AND '2018-01-02'.

ОДНАКО , в среднем, я хочу разделить на общее количество Date с, НЕ ТОЛЬКО ДЛЯ ЭТОГО Id2.

Итак, мой набор результатов будет:

Id2:       AvgVal:
A          1+1 / 2 = 1
B          1+1 / 2 = 1
C          1 / 2 = 0.5

Обратите внимание, что значение C делится на 2, хотя в этом диапазоне дат есть только 1 значение для C (другими словами, мы делим только на COUNT(DISTINCT Date) OVER (PARTITION BY Id1). Не добавляем дополнительную группировку на Id2.

Я придумал способ сделать это, используя CTE, и могу придумать способ сделать это, сохраняя делитель во временной переменной, но я ДЕЙСТВИТЕЛЬНО пытаюсь продумать, есть ли способ сделать это в одном операторе SELECT.

Мое текущее решение выглядит следующим образом:

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

И, как я уже сказал, я думаю, что я мог бы также сделать это, присвоив локальной переменной значение MaxNumDates, но я действительно пытаюсь увидеть, есть ли способ сделать это с помощью одного запроса с некоторыми форма разбиения / агрегации - при условии, конечно, это лучший способ сделать это.

Есть мысли?

Спасибо!

1 Ответ

0 голосов
/ 28 августа 2018

Поскольку ваш count(distinct Date) будет одинаковым для всего набора результатов, почему бы НЕ просто взять его в отдельную переменную и использовать его,

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)
;

-- a variable to hold the count of distinct dates
declare @distinctDates int;

-- here we are reading the value in variable
select  @distinctDates = count(distinct t.[Date])
from    @Tbl1 as t
where   t.[Date] between @StartDate and @EndDate
        and t.Id1 = @id1

select  t.Id2, sum(t.[Value]) as sumOfValue, @distinctDates as distinctDates
        ,  sum(t.[Value]) / @distinctDates as AvgVal 
from    @Tbl1 as t
where   t.[Date] between @StartDate and @EndDate
        and t.Id1 = @id1
group by t.Id2
...