2

私の想像上の結果は次のようになります。

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

つまり、年間およびカテゴリごとのトランザクションの合計です。

カテゴリによっては、 1年間取引がない場合があります。そのような場合、結果の 2 行目は表示されません。すべてのカテゴリに 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; 
4

3 に答える 3

1

パーティション化された外部結合では、カテゴリ テーブルは必要ありません。

「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 でフィルター処理を行い、その列にインデックスがある場合は、それを使用できます。もう 1 つのオプションは、単純に trunc(t.trans_date) = y.year をオン条件として使用することです。

お役に立てれば。

よろしく、
ロブ。

于 2012-06-13T15:26:47.630 に答える
1

理想的には、カテゴリのテーブルと年のテーブルが必要です。

select c.category, y.year, nvl(sum(t.trans_value),0)
from categories c
cross join years y
left outer join transaction t
   on  to_char(t.trans_date, 'YYYY') = y.year
   and t.category = c.category
group by c.category, y.year
order by 1, 2; 

カテゴリの表があることを願っていますが、年の表がない可能性があります。その場合、次のように「偽造」できます。

with years as
( select 2007+rownum year
  from dual
  connect by rownum < 10) -- returns 2008, 2009, ..., 2017
select c.category, y.year, nvl(sum(t.trans_value),0)
from categories c
cross join years y
left outer join transaction t
   on  to_char(t.trans_date, 'YYYY') = y.year
   and t.category = c.category
group by c.category, y.year
order by 1, 2; 
于 2012-06-13T14:06:27.550 に答える
0

完全な実際の例を次に示します。

CREATE TABLE transactions (CATEGORY VARCHAR(1), trans_date DATE, trans_value NUMBER(25,8));
CREATE TABLE YEAR (YEAR NUMBER(4));

CREATE TABLE categories (CATEGORY VARCHAR(1));
INSERT INTO categories VALUES ('A');
INSERT INTO categories VALUES ('B');

INSERT INTO transactions VALUES ('A',to_date('2008-01-01','YYYY-MM-DD'),100.0);
INSERT INTO transactions VALUES ('A',to_date('2008-02-01','YYYY-MM-DD'),100.0);

INSERT INTO transactions VALUES ('B',to_date('2008-01-01','YYYY-MM-DD'),50.0);
INSERT INTO transactions VALUES ('B',to_date('2008-02-01','YYYY-MM-DD'),50.0);

INSERT INTO transactions VALUES ('B',to_date('2009-08-01','YYYY-MM-DD'),5.0);

INSERT INTO YEAR VALUES (2008);
INSERT INTO YEAR VALUES (2009);


SELECT b.category
     , b.year
     , SUM(nvl(a.trans_value,0))
  FROM (SELECT to_char(a.trans_date,'YYYY') YEAR
             , CATEGORY
             , SUM(NVL(trans_value,0)) trans_value
          FROM transactions a
        GROUP BY to_char(a.trans_date,'YYYY')
               , a.category ) a
     , (SELECT
        DISTINCT a.category
               , b.year
          FROM   categories a
             ,   YEAR b ) b
 WHERE b.year = to_char(a.year(+))
   AND b.category = a.category(+)
 GROUP BY
       b.category
     , b.year  
 ORDER BY 1
         ,2;

出力:

    CATEGORY    YEAR    SUM(NVL(A.TRANS_VALUE,0))
1   A           2008    200
2   A           2009    0
3   B           2008    100
4   B           2009    5
于 2012-06-13T13:58:33.537 に答える