我需要找到每个月的值总和,然后找到月份的最大值。我有点难过,不知道该怎么做。
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
帮助!
答案 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)
换句话说,您需要CASE
或DECODE()
,但不能同时使用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)
更聪明,否则如果一个或多个条目中的条目为零,您将得到错误的平均值几个月的兴趣。