Oracle PARTITION BY GROUPING_ID 和 SUM
Posted
技术标签:
【中文标题】Oracle PARTITION BY GROUPING_ID 和 SUM【英文标题】:Oracle PARTITION BY GROUPING_ID with SUM 【发布时间】:2016-01-03 00:34:49 【问题描述】:我正在尝试实现一个简单的数据仓库分析查询,处理“YEAR_VALUE”、“MONTH_VALUE”和“INVOICE_COST”
SELECT YEAR_VALUE, MONTH_VALUE, SUM (INVOICE_VALUE) AS TOTAL_INVOICE,
RANK () OVER (PARTITION BY GROUPING_ID (YEAR_VALUE, MONTH_VALUE) ORDER BY SUM (INVOICE_VALUE) DESC) AS YEAR_RANK,
RANK () OVER (PARTITION BY YEAR_VALUE, GROUPING_ID (MONTH_VALUE) ORDER BY SUM (INVOICE_VALUE) DESC) AS MONTH_RANK
FROM FACT_WH
JOIN TIME_WH ON TIME_WH.TIME_ID = FACT_WH.TIME_ID
GROUP BY (YEAR_VALUE, MONTH_VALUE);
输出是: Output
“YEAR_RANK”应表示与其他年份相比的年度总发票价值,2016 年的 YEAR_RANK=1,2015 年的 YEAR_RANK=2
问题是 'YEAR_RANK' 的值是 1,2,3,4,5 它应该是 1,1,2,2,1 我在我的代码中找不到问题,它可能在第 2 行,我尝试了所有方法并且已经浪费了很多时间。
提前致谢。
【问题讨论】:
要回答这类问题,提供表结构的描述、提供一些示例输入数据以及所需的输出总是非常有用的。如果您能提供SQLFiddle,那就更好了。 我认为您的 grouping_id 年份排名应该只包含 YEAR_VALUE 而不是 YEAR_VALUE 和 MONTH_VALUE 【参考方案1】:一个好的方法,尤其是在查询很复杂和/或提供令人困惑的结果的情况下,是将整个查询划分为子查询,每个子查询解决一个特定的任务。
在您的情况下,我建议首先攻击 事实和维度表的联接,并按年份和月份分组以计算 total_invoice
你会得到这样的结果
YEAR_VALUE MONTH_VALUE TOTAL_INVIOCE
---------- ----------- -------------
2016 3 29960
2016 1 10700
2015 11 5100
2015 8 1680
2016 2 800
请注意,您不需要任何 GROUP BY 扩展,例如 GROUPING_ID,您将使用分析函数解决所有问题
在下一步中(使用先前的结果作为因子子查询)您计算年份和月份的总数 - 使用 SUM
的分析版本。
在最后一步中,您计算 RANK。请注意,您需要的年份 一个 DENSE_RANK,否则你会被“跳过”排名,例如 1,3(由于一年的重复记录)。
year_rank
根本没有分区,month_rank
在 YEAR 分区,因为您订购了一年中的月份。
with data as (
-- perform join and group by in this subquery
select 2016 year_value, 3 month_value, 29960 total_invioce from dual union all
select 2016 year_value, 1 month_value, 10700 total_invioce from dual union all
select 2015 year_value, 11 month_value, 5100 total_invioce from dual union all
select 2015 year_value, 8 month_value, 1680 total_invioce from dual union all
select 2016 year_value, 2 month_value, 800 total_invioce from dual),
year_month as (
-- perform year and month summary here
select
year_value, month_value, total_invioce,
sum(total_invioce) over (partition by year_value) total_invoice_year,
sum(total_invioce) over (partition by month_value) total_invoice_month
from data
)
-- perform ranking here
select year_value, month_value, total_invioce,
dense_rank() OVER (ORDER BY total_invoice_year DESC) year_rank,
rank() OVER (partition by year_value ORDER BY total_invoice_month DESC) month_rank
from year_month
order by total_invioce desc;
YEAR_VALUE MONTH_VALUE TOTAL_INVIOCE YEAR_RANK MONTH_RANK
---------- ----------- ------------- ---------- ----------
2016 3 29960 1 1
2016 1 10700 1 2
2015 11 5100 2 1
2015 8 1680 2 2
2016 2 800 1 3
【讨论】:
以上是关于Oracle PARTITION BY GROUPING_ID 和 SUM的主要内容,如果未能解决你的问题,请参考以下文章
如何在不使用 GROUP BY 或 PARTITION BY 的情况下对 Oracle SQL 中的数据进行分组
SQL Server: Difference between PARTITION BY and GROUP BY
使用 OVER (PARTITION BY ) 而不是 Group By
over partition by与group by 的区别