oracle - 如何按类别、年份进行分组,以便每个类别每年的总和为零?

标签 oracle group-by

我的想象结果如下:

Category | Year |  sum  |
--------- ------ --------
    A      2008    200
    A      2009      0
    B      2008    100
    B      2009      5
   ...     ...     ...   

即每和每个类别交易量总和。

在某些情况下,类别一年内没有任何交易。在这种情况下,结果的第二行将不会出现。我必须如何重写上述查询才能为每个类别包含 2008 年、2009 年?

select category, to_char(trans_date, 'YYYY') year, sum(trans_value)
from transaction
group by category, to_char(trans_date, 'YYYY')
order by 1, 2; 

最佳答案

带有partitioned outer join ,您不需要类别表。

我使用了与“dcp”相同的事务表:

SQL> create table transactions
  2  ( category varchar(1)
  3  , trans_date date
  4  , trans_value number(25,8)
  5  );

Table created.

SQL> insert into transactions values ('A',to_date('2008-01-01','yyyy-mm-dd'),100.0);

1 row created.

SQL> insert into transactions values ('A',to_date('2008-02-01','yyyy-mm-dd'),100.0);

1 row created.

SQL> insert into transactions values ('B',to_date('2008-01-01','yyyy-mm-dd'),50.0);

1 row created.

SQL> insert into transactions values ('B',to_date('2008-02-01','yyyy-mm-dd'),50.0);

1 row created.

SQL> insert into transactions values ('B',to_date('2009-08-01','yyyy-mm-dd'),5.0);

1 row created.

对于分区外连接,您只需要一组年份来对外连接进行分区。在下面的查询中,我使用了 2 年(2008 年和 2009 年),但您可以轻松调整该设置。

SQL> with the_years as
  2  ( select 2007 + level year
  3         , trunc(to_date(2007 + level,'yyyy'),'yy') start_of_year
  4         , trunc(to_date(2007 + level + 1,'yyyy'),'yy') - interval '1' second end_of_year
  5      from dual
  6   connect by level <= 2
  7  )
  8  select t.category                "Category"
  9       , y.year                    "Year"
 10       , nvl(sum(t.trans_value),0) "sum"
 11    from the_years y
 12         left outer join transactions t
 13           partition by (t.category)
 14           on (t.trans_date between y.start_of_year and y.end_of_year)
 15   group by t.category
 16       , y.year
 17   order by t.category
 18       , y.year
 19  /

Category       Year        sum
-------- ---------- ----------
A              2008        200
A              2009          0
B              2008        100
B              2009          5

4 rows selected.

另请注意,我使用了 start_of_year 和 end_of_year,因此如果您想过滤 trans_date 并且您在该列上有索引,则可以使用它。另一种选择是简单地使用 trunc(t.trans_date) = y.year 作为条件。

希望这有帮助。

问候,
罗布。

关于oracle - 如何按类别、年份进行分组,以便每个类别每年的总和为零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11016427/

相关文章:

c# - 在一个连接中执行多个 UPDATE 语句的最佳方法是什么?

mysql - 在 GROUP BY 中使用 LIMIT 以获得每组 N 个结果?

r - 基于几个不同的(子)分组(列)计算一列中唯一字符元素的数量

ruby:根据日期所在的星期将日期数组分组为散列,并将键作为每周的第一个日期

linux - 如何从外网访问virtual box web服务器url

oracle - PLS-00103 : Encountered the symbol "end-of-file" when expecting one of the following: := . (%;

c - 错误 LNK2001 : unresolved reference with Pro*C code with Visual C++

sql - 当您 DROP USER 但未指定 CASCADE 时,模式对象会发生什么情况?

python - Pandas:通过数据框聚合数据

mysql - Over() 函数未按预期覆盖所有行