базовый sql: выбор значений AVG() из одного и того же столбца несколько раз в одном запросе, когда каждое требуемое значение AVG() использует другое предложение WHERE

Я хочу получить три разных средних значения из одного столбца (value_to_count) внутри одной таблицы, где все эти средние значения имеют другое предложение WHERE (в зависимости от времени).

Пример данных:

###services#### Table
service_id       value_to_count                time
-----------      -----------------------       ---------
     604                    2054               04:04:50
     604                    3444               05:00:15
     604                    2122               07:12:50
     604                    2144               09:10:50
     604                    2001               13:12:53
     602                    2011               15:00:12
     602                    2115               17:22:35
     602                    1411               20:22:12
     602                    1611               21:04:52
     602                    2111               23:43:45

Я использую этот запрос в данный момент, чтобы получить среднее значение по времени между 18 и 23:

Запрос

SELECT 
service_id AS service, AVG(value_to_count) AS primetime 
FROM services 
WHERE HOUR(time) BETWEEN 18 AND 23 
GROUP BY service_id

И это дает мне такие результаты:

### Result #### 
service          primetime
-----------      --------------      
     604               2154           
     602               2444           

Теперь я хочу получить другие средние значения рядом с тем, что я уже получил. На этот раз я просто хочу получить средние значения «ЧАС (время) МЕЖДУ 06 И 18» и «ЧАС (время) МЕЖДУ 23 И 06».

Это форма результата, которую я хочу получить:

### Wanted Result #### 
service          primetime          other_time_interval_1   other_time_interval_2
-----------      --------------     ----------------        ------------------
     604               2154              2352                      1842
     602               2444              4122                      1224

person ranssi    schedule 27.02.2012    source источник
comment
BETWEEN 23 and 06 не будет работать. Его нужно разделить на два отдельных условия. Кроме того, вы, кажется, дважды считаете события в часы 18, 23 и 06, поскольку оба предела включены.   -  person Damien_The_Unbeliever    schedule 27.02.2012


Ответы (2)


Это должно сделать это:

SELECT service_id AS service, 
       AVG(case when HOUR(time) BETWEEN 18 AND 23 then value_to_count else null end) AS primetime,
       AVG(case when HOUR(time) BETWEEN 06 AND 18 then value_to_count else null end) AS other_time_interval_1
FROM services 
GROUP BY service_id
person a_horse_with_no_name    schedule 27.02.2012
comment
Это сделало работу для получения трех разных результатов, как я и имел в виду. Большое спасибо за это. Теперь я заметил, что мой «ЧАС (время) МЕЖДУ 23 И 06» дает мне NULL, потому что он не может сравнивать час просто так. Я попытался добавить два условия в одно предложение «case when», разделенное AND или запятой, но я просто снова получил NULL или ошибки. Есть ли способ сравнить время с 23 до 24, а затем с 00 до 06 в одном и том же «случай, когда»? - person ranssi; 27.02.2012
comment
Как указал ОП, BETWEEN 23 and 06 не сработает. Это должно быть разделено на два отдельных условия - person Damien_The_Unbeliever; 27.02.2012
comment
@Damien_The_Unbeliever: ах, правильно (скопируйте и вставьте, не задумываясь...) - person a_horse_with_no_name; 27.02.2012

Я бы сначала определил периоды для каждого фрагмента данных, а затем беспокоился о группировке и усреднении:

;With ServicePeriods as (
    SELECT Service_id,value_to_count,
       CASE WHEN HOUR(time) between 18 and 22 THEN 1
            WHEN HOUR(time) between 06 and 17 THEN 2
            ELSE 3 END as period
    FROM Services
)
select Service_Id,
    AVG(CASE WHEN period=1 THEN value_to_count END) as prime_time,
    AVG(CASE WHEN period=2 THEN value_to_count END) as other_time_interval_1,
    AVG(CASE WHEN period=3 THEN value_to_count END) as other_time_interval_2
from
    ServicePeriods
group by Service_id

(На самом деле, сначала я сделал это как вывод в виде 3 отдельных строк, но теперь я повернулся в соответствии с вашими запрошенными результатами)

Поскольку мой первый CASE охватывает все периоды, мне не нужно думать о "между 23 и 06". Обратите внимание, что я также скорректировал диапазоны, чтобы избежать двойного счета.

Если вы хотите явно проверить HOUR(time) between 23 and 06 (или 05), вы можете сделать HOUR(time) >= 23 or HOUR(time) <= 6 (или <). Обратите внимание, что вам нужно OR, а не AND

person Damien_The_Unbeliever    schedule 27.02.2012
comment
Спасибо за ответы. Очень расширил мой взгляд. - person ranssi; 27.02.2012