5

以下のように、エンティティ名、年、アクティビティ番号の表があります。何年かの間、何の活動もありません。

name | year | act_num
-----+------+---------
aa   | 2000 |       2
aa   | 2001 |       6
aa   | 2002 |       9
aa   | 2003 |      15
aa   | 2005 |      17
b    | 2000 |       3
b    | 2002 |       4
b    | 2003 |       9
b    | 2005 |      12
b    | 2006 |       2

postgresqlで作成するには;

CREATE TABLE entity_year_activity (
name character varying(10),
year integer,
act_num integer
);

INSERT INTO entity_year_activity
VALUES
    ('aa', 2000, 2),
    ('aa', 2001, 6),
    ('aa', 2002, 9),
    ('aa', 2003, 15),
    ('aa', 2005, 17),
    ('b', 2000, 3),
    ('b', 2002, 4),
    ('b', 2003, 9),
    ('b', 2005, 12),
    ('b', 2006, 2);

過去x年間の合計数と、各事業体の今年の活動数を以下のようにしたいと思います。

x=3年の例として。

name | year | act_num | total_3_years
-----+------+---------+---------------
aa   | 2000 |       2 |      2
aa   | 2001 |       6 |      8
aa   | 2002 |       9 |     17
aa   | 2003 |      15 |     30
aa   | 2004 |       0 |     24
aa   | 2005 |      17 |     32
b    | 2000 |       3 |      3
b    | 2001 |       0 |      3
b    | 2002 |       4 |      7
b    | 2003 |       9 |     13
b    | 2005 |      12 |     21
b    | 2006 |       2 |     14
4

4 に答える 4

3

sumこれは、範囲ベースのウィンドウフレームでウィンドウ関数として集計を使用する機能を使用するアプローチです。ウィンドウフレーミングSUM(...) OVER (PARTITION BY name ORDER BY year ROWS 2 PRECEDING)を参照してください。

WITH name_years(gen_name, gen_year) AS (
  SELECT gen_name, s
  FROM generate_series(
    (SELECT min(year) FROM entity_year_activity),
    (SELECT max(year) FROM entity_year_activity)
  ) s CROSS JOIN (SELECT DISTINCT name FROM entity_year_activity) n(gen_name)
),
windowed_history(name, year,act_num,last3_actnum) AS (
  SELECT
    gen_name, gen_year, coalesce( act_num, 0),
    SUM(coalesce(act_num,0)) OVER (PARTITION BY gen_name ORDER BY gen_year ROWS 2 PRECEDING)
  FROM name_years 
  LEFT OUTER JOIN entity_year_activity ON (gen_name = name AND gen_year = year)
)
SELECT name, year, act_num, sum(last3_actnum) as total_3_years
FROM windowed_history
GROUP BY name, year, act_num
HAVING sum(last3_actnum) <> 0
ORDER BY name, year;

SQLFiddleを参照してください。

エントリ自体がない年のエントリを生成する必要があるため、このクエリは複雑になります。すべての(名前、年)ペアのテーブルを生成しleft outer join entity_year_activity、ウィンドウの合計を実行する前にそのテーブルに作成するので、すべての名前セットのすべての年が表されます。これがとても複雑な理由です。次に、集計結果をフィルタリングして、合計がゼロのエントリを除外します。

于 2012-10-25T13:31:14.107 に答える
3

SQL フィドル

select
    s.name,
    d "year",
    coalesce(act_num, 0) act_num,
    coalesce(act_num, 0)
    + lag(coalesce(act_num, 0), 1, 0) over(partition by s.name order by d)
    + lag(coalesce(act_num, 0), 2, 0) over(partition by s.name order by d)
    total_3_years
from
    entity_year_activity eya
    right join (
        generate_series(
            (select min("year") from entity_year_activity),
            (select max("year") from entity_year_activity)
        ) d cross join (
        select distinct name
        from entity_year_activity
        ) f
    ) s on s.name = eya.name and s.d = eya."year"
order by s.name, d
于 2012-10-25T13:16:29.373 に答える
2
SELECT en_key.name, en_key.year, en_key.act_num, SUM(en_sum.act_num) as total_3_years
FROM entity_year_activity en_key
  INNER JOIN entity_year_activity en_sum
     ON en_key.name = en_sum.name
WHERE en_sum.year BETWEEN en_key.year - 2 AND en_key.year
GROUP BY en_key.name, en_key.year
于 2012-10-25T13:09:15.353 に答える
1

別の試み。ただし、これには 0 行の年がありません。

select t1.name, t1.year, t1.act_num,
      (select sum(t2.act_num) from entity_year_activity t2
                              where t2.year between t1.year - 2 and t1.year
                                    and t2.name = t1.name) total
from entity_year_activity t1;
于 2012-10-25T14:20:49.227 に答える