【问题标题】:How to count ratio hourly?如何计算每小时的比率?
【发布时间】:2018-09-18 13:46:51
【问题描述】:

在执行查询时,我对自己的进一步操作有点理解。

我有两个表 "A"(date, response, b_id) 和 "B"(id, country)。我需要计算存在响应的条目数量与特定日期的条目总数的每小时比率。最终选择应包括“小时”、“比率”列。

SELECT COUNT(*) FROM A WHERE RESPONSE IS NOT NULL//counting entries with response
SELECT COUNT(*) FROM A//counting total number of entries
  1. 如何计算比率?我应该为它创建一个单独的变量吗?
  2. 如何计算一天中的每个小时?我应该像循环一样吗? + 如何获取日期的“小时”部分?
  3. 选择小时数和计数比率的最佳方法是什么?我应该为它单独制作一张桌子吗?

对于复杂的查询我比较陌生,所以我很乐意得到各种帮助

【问题讨论】:

  • 请提供样本数据和期望的结果。

标签: sql oracle


【解决方案1】:

你可以这样做:

select to_char(datecol, 'HH24') as hour,
       count(response) as has_response, count(*) as total,
       count(response) / count(*) as ratio
from a
where datecol >= date '2018-09-18' and datecol < date '2018-09-19'
group by to_char(datecol, 'HH24');

您也可以使用avg() 执行此操作——这也很有趣:

select to_char(datecol, 'HH24'),
       avg(case when response is not null then 1.0 else 0 end) as ratio
from a
where datecol >= date '2018-09-18' and datecol < date '2018-09-19'
group by to_char(datecol, 'HH24')

不过,在这种情况下,这需要更多的输入。

【讨论】:

  • 对不起,伙计,我想投票并点击了上箭头,但堆栈溢出引发了一个奇怪的错误
  • 非常感谢您的帮助,谢谢。我会试试的
  • 请注意,如果您不考虑日期,您最终会混淆多个不同日期的小时数。因此,对于特定日期(例如 9 月 1 日 13:00 至 13:59),它们将不准确,而是(全天 13:00 至 13:59)。您确实尝试通过过滤特定日期来进行补偿,but this means your query doesn't work for more than one day!
  • 当我尝试第一个变体时,它会抛出一个异常“不是单组组函数”。我发现这可能是因为在 SELECT 中使用了 COUNT 函数
【解决方案2】:

SQL Fiddle

Oracle 11g R2 架构设置:

CREATE TABLE A ( dt, response, b_id ) AS
  SELECT DATE '2018-09-18' + INTERVAL '00:00' HOUR TO MINUTE, NULL, 1 FROM DUAL UNION ALL
  SELECT DATE '2018-09-18' + INTERVAL '00:10' HOUR TO MINUTE, 'A',  1 FROM DUAL UNION ALL
  SELECT DATE '2018-09-18' + INTERVAL '00:20' HOUR TO MINUTE, 'B',  1 FROM DUAL UNION ALL
  SELECT DATE '2018-09-18' + INTERVAL '01:00' HOUR TO MINUTE, 'C',  1 FROM DUAL UNION ALL
  SELECT DATE '2018-09-18' + INTERVAL '01:10' HOUR TO MINUTE, 'D',  1 FROM DUAL UNION ALL
  SELECT DATE '2018-09-18' + INTERVAL '02:00' HOUR TO MINUTE, NULL, 1 FROM DUAL UNION ALL
  SELECT DATE '2018-09-18' + INTERVAL '03:00' HOUR TO MINUTE, 'E',  1 FROM DUAL UNION ALL
  SELECT DATE '2018-09-18' + INTERVAL '05:10' HOUR TO MINUTE, 'F',  1 FROM DUAL;

查询 1:

SELECT b_id,
       TO_CHAR( TRUNC( dt, 'HH' ), 'YYYY-MM-DD HH24:MI:SS' ) AS hour,
       COUNT(RESPONSE) AS total_response_per_hour,
       COUNT(*)        AS total_per_hour,
       total_response_per_day,
       total_per_day,
       COUNT(response) / total_response_per_day AS ratio_for_responses,
       COUNT(*) / total_per_day AS ratio
FROM   (
  SELECT A.*,
         COUNT(RESPONSE) OVER ( PARTITION BY b_id, TRUNC( dt ) ) AS total_response_per_day,
         COUNT(*) OVER ( PARTITION BY b_id, TRUNC( dt ) ) AS total_per_day
  FROM   A
)
GROUP BY
       b_id,
       total_per_day,
       total_response_per_day,
       TRUNC( dt, 'HH' )
ORDER BY
       TRUNC( dt, 'HH' )

Results:

| B_ID |                HOUR | TOTAL_RESPONSE_PER_HOUR | TOTAL_PER_HOUR | TOTAL_RESPONSE_PER_DAY | TOTAL_PER_DAY | RATIO_FOR_RESPONSES | RATIO |
|------|---------------------|-------------------------|----------------|------------------------|---------------|---------------------|-------|
|    1 | 2018-09-18 00:00:00 |                       2 |              3 |                      6 |             8 |  0.3333333333333333 | 0.375 |
|    1 | 2018-09-18 01:00:00 |                       2 |              2 |                      6 |             8 |  0.3333333333333333 |  0.25 |
|    1 | 2018-09-18 02:00:00 |                       0 |              1 |                      6 |             8 |                   0 | 0.125 |
|    1 | 2018-09-18 03:00:00 |                       1 |              1 |                      6 |             8 | 0.16666666666666666 | 0.125 |
|    1 | 2018-09-18 05:00:00 |                       1 |              1 |                      6 |             8 | 0.16666666666666666 | 0.125 |

【讨论】:

    【解决方案3】:
       SELECT withResponses.hour,
           withResponses.cnt AS withResponse,
           alls.cnt AS AllEntries,
           (withResponses.cnt / alls.cnt) AS ratio
    FROM
      ( SELECT to_char(d, 'DD-MM-YY - HH24') || ':00 to :59 ' hour,
               count(*) AS cnt
       FROM A
       WHERE RESPONSE IS NOT NULL
       GROUP BY to_char(d, 'DD-MM-YY - HH24') || ':00 to :59 ' ) withResponses,
    
      ( SELECT to_char(d, 'DD-MM-YY - HH24') || ':00 to :59 ' hour,
               count(*) AS cnt
       FROM A
       GROUP BY to_char(d, 'DD-MM-YY - HH24') || ':00 to :59 ' ) alls
    WHERE alls.hour = withResponses.hour ;
    

    SQLFiddle:http://sqlfiddle.com/#!4/c09b9/2

    【讨论】:

    • 感谢您的回答! “alls”和“withResponses”指的是哪些表?
    • Alls = 包含所有响应的别名子查询。 WithResponses = 响应不为空的别名子表。
    猜你喜欢
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-12
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    相关资源
    最近更新 更多