【问题标题】:basic sql : selecting AVG() values from the same column multiple times in one query, when each wanted AVG() value uses different WHERE clause基本 sql:当每个想要的 AVG() 值使用不同的 WHERE 子句时,在一个查询中多次从同一列中选择 AVG() 值
【发布时间】:2012-03-16 19:11:00
【问题描述】:

我想从一张表中的一列 (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           

现在我想在我已经得到的平均值旁边获得其他平均值。这次我只想获得“HOUR(time) BETWEEN 06 AND 18”和“HOUR(time) BETWEEN 23 AND 06”的平均值。

这是我想要得到的结果形式:

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

【问题讨论】:

  • BETWEEN 23 and 06 不起作用。它必须分成两个独立的条件。此外,您似乎重复计算了 18、23 和 06 小时的事件,因为这两个限制都包含在内。

标签: sql average multiple-conditions


【解决方案1】:

应该这样做:

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

【讨论】:

  • 这样就得到了我想的三个不同的结果。为此非常感谢。现在我注意到我的 'HOUR(time) BETWEEN 23 AND 06' 给了我 NULL 因为它不能像那样比较小时。我试图在一个用 AND 或逗号分隔的“case when”子句中添加两个条件,但我又得到了 NULL 或错误。有什么方法可以在同一个“case when”内比较从 23 到 24 再从 00 到 06 的时间?
  • 正如 OP 所指出的,BETWEEN 23 and 06 是行不通的。它必须分成两个独立的条件
  • @Damien_The_Unbeliever:啊,对(复制粘贴不假思索...)
【解决方案2】:

我会先定义每条数据的周期,然后再考虑分组和平均:

;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

【讨论】:

  • 感谢您的回答。开阔了我的视野。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多