按月找到值的总和,然后找到最大的月份总和

时间:2015-03-27 17:18:01

标签: sql database oracle max

我需要找到每个月的值总和,然后找到月份的最大值。我有点难过,不知道该怎么做。

My customer wants it formatted a particular way:

Activity |  JUN  |  JUL  |  AUG  |  MIN  |   MAX  |  AVG
jogging  |  232  |   32  |  343  |   32  |   343  |  202 

Here is my table:

activity + status + date
____________________________
swimming +    1   + 13-DEC-02
swimming +    1   + 12-FEB-01
jogging  +    0   + 14-AUG-03

这是我到目前为止所做的:

SELECT ACTIVITY,
  SUM(
  CASE
    WHEN DECODE(TO_CHAR((TRUNC(date)), 'MON'),'JUL','JUL') IN 'JUL'
    THEN 1
    ELSE 0
  END ) JUL,
  SUM(
  CASE
    WHEN DECODE(TO_CHAR((TRUNC(date)), 'MON'),'AUG','AUG') IN 'AUG'
    THEN 1
    ELSE 0
  END ) AUG
FROM daily_log
WHERE ACTIVITY_DESC IN ('Swimming','Jogging')
AND TRUNC(date) BETWEEN '01-JUL-2014' AND '30-JUN-2015'
AND STATUS = 1
group by ACTIVITY

帮助!

3 个答案:

答案 0 :(得分:0)

对于MIN / MAX,您可以使用GREATEST和LEAST,如果您只需要从结果中选择值。您可以使用MIN,MAX和AVG函数直接从源数据中聚合值。

http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions001.htm

此外,您可能希望查看使用子查询,尤其是使用WITH子句。要选择中间结果,您可以将它们组合在一起。

http://oracle-base.com/articles/misc/with-clause.php

关于SUM(CASE位,您可以访问PIVOT作为将行转换为列的选项。

http://oracle-base.com/articles/11g/pivot-and-unpivot-operators-11gr1.php

编辑: 像这样的东西应该这样做

SELECT Activity,
  COALESCE(AUG,0) AS AUG,
  COALESCE(JUN,0) AS JUN,
  COALESCE(JUL,0) AS JUL,
  MIN,MAX,AVG
FROM (
    SELECT
      Mon,
      Activity,
      Count, 
      MIN(Count) OVER (PARTITION BY Activity) AS Min,
      MAX(Count) OVER (PARTITION BY Activity) AS Max,
      AVG(Count) OVER (PARTITION BY Activity) AS Avg
    FROM (
      SELECT TO_CHAR("date",'MON') AS Mon, activity, COUNT(*) Count
      FROM daily_log
      GROUP BY TO_CHAR("date",'MON'), activity
    )
) PIVOT ( SUM(Count) FOR Mon IN ('AUG' AS AUG, 'JUN' AS JUN, 'JUL' AS JUL))

答案 1 :(得分:0)

您的查询有点过于复杂。例如:

CASE
    WHEN DECODE(TO_CHAR((TRUNC(date)), 'MON'),'AUG','AUG') IN 'AUG'
    THEN 1
    ELSE 0
END

可以改写为:

CASE WHEN TO_CHAR(date, 'MON') = 'AUG' THEN 1 ELSE 0 END

甚至:

DECODE(TO_CHAR(date, 'MON'), 'AUG', 1, 0)

换句话说,您需要CASEDECODE(),但不能同时使用SELECT activity , SUM(DECODE(TO_CHAR(date, 'MON'), 'JUL', 1, 0)) AS jul , SUM(DECODE(TO_CHAR(date, 'MON'), 'AUG', 1, 0)) AS aug FROM daily_log WHERE activity_desc IN ('Swimming','Jogging') AND date >= DATE'2014-07-01' AND date < DATE'2015-07-01' AND status = 1 GROUP BY activity; date。考虑到这一点,我们可以稍微重写您的查询:

DATE

现在,请注意我在TRUNC()列上更改了您的过滤器(顺便说一下,这是一个糟糕的列名,因为DATE是一个Oracle关键字,用于数据类型和对于ANSI日期文字)。您希望避免在LEAST()列上使用GREATEST(),特别是如果它已被编入索引(并且如果它未被编入索引,您可能需要考虑将其编入索引)。由于您需要所有月份的最小值和最大值,因此您需要使用SELECT activity, jul, aug , LEAST(jul, aug) AS min , GREATEST(jul, aug) AS max , (jul+aug)/2 AS avg FROM ( SELECT activity , SUM(DECODE(TO_CHAR(date, 'MON'), 'JUL', 1, 0)) AS jul , SUM(DECODE(TO_CHAR(date, 'MON'), 'AUG', 1, 0)) AS aug FROM daily_log WHERE activity_desc IN ('Swimming','Jogging') AND date >= DATE'2014-07-01' AND date < DATE'2015-07-01' AND status = 1 GROUP BY activity ); LEAST()函数:

GREATEST()

不幸的是,{{1}}和{{1}}没有任何内容可以计算平均值,因此我们必须手动执行此操作。在添加额外月份的结果时,您希望增加分母。

答案 2 :(得分:0)

您希望聚合两次:一次计算每月汇总,第二次计算这些汇总的统计数据。这需要(至少)两个查询,一个在另一个范围内作为公用表表达式,内联视图或子查询。例如:

SELECT
  activity,
  SUM(
    CASE month
      WHEN 7 THEN count
      ELSE 0
    END
  ) JUL,
  SUM(
    CASE month
      WHEN 8 THEN count
      ELSE 0
    END
  ) AUG,
  AVG(count) AS avg,
  MAX(count) AS max
FROM (
  SELECT
    activity,
    EXTRACT(MONTH FROM "date") AS month,
    COUNT(*) AS count
  FROM daily_log
  WHERE
    ACTIVITY_DESC IN ('Swimming','Jogging')
    AND TRUNC("date") BETWEEN '01-JUL-2014' AND '30-JUN-2015'
    AND STATUS = 1
  group by ACTIVITY, EXTRACT(MONTH FROM "date")
)
GROUP BY activity

请注意,在您的真实查询中,您可能希望比AVG(count)更聪明,否则如果一个或多个条目中的条目为零,您将得到错误的平均值几个月的兴趣。