1

前年の利益を特定の年の週まで表示する列を作成する必要があります。したがって、現在の年を週に分割し、特定の週の利益を示します。より明確にするために、前年の利益が 1000 だったとしましょう。今年の最初の週の利益は 100、2 番目の週は 200、3 番目は -100 (損失) などです。したがって、次のようになります。

week1|week2|week3|
1100 |1300 |1200 |

私が試したのは:

SELECT
CASE when f1.year = DATE_PART('year', now()) THEN f1.week END as week,
profit as profit
FROM (
SELECT 
DATE_PART('week', so.date_order) as week,
DATE_PART('year', so.date_order) as year,
so.profit as profit
FROM
sale_order as so
GROUP BY
week, year, profit
WHERE
so.date_order >= date_trunc('year', now() - '1 year'::interval)::timestamp::date  and so.date_order <= date_trunc('year', now()+ '1 year'::interval)::timestamp::date-1 
)as f1
GROUP BY
week, profit
ORDER BY
week

しかし、これは必要に応じて機能していません。これは、特定の週ごとに利益を分割するためです。つまり、その週の利益のみが表示されますが、「その週の利益」+「前年度の利益」が必要です。

ウィンドウ関数を試す私のクエリ:

(
SELECT
x.id as id,week as week, x.last_year_profit + y.running_profit as week_profit
FROM
(
SELECT
min(sol.id) as id,
 --DATE_PART('year',  so.date_order) AS calcyear, DATE_PART('week',  so.date_order) AS calcweek,
sum(sol.price_subtotal - (CASE WHEN sol.account_cost_amount != 0 THEN sol.account_cost_amount ELSE sol.purchase_price END )) as last_year_profit
-- sum(sol.price_subtotal) as price_unit, sum(sol.purchase_price) as purchase_price, sum(sol.account_cost_amount) as account_cost_amount
FROM
sale_order as so
INNER JOIN sale_order_line as sol ON (sol.order_id = so.id)
INNER JOIN res_partner as rp ON (so.partner_id = rp.id)
WHERE EXISTS (
SELECT * FROM  res_partner_category_rel rpcl
WHERE 
rpcl.partner_id=rp.id and rpcl.category_id=37
and (so.date_order >= date_trunc('year', now() - '1 year'::interval)::timestamp::date  and so.date_order <= date_trunc('year', now())::timestamp::date-1 )
and so.state != 'cancel'
)
) as x
CROSS JOIN (
SELECT
date_trunc('week', so.date_order) as week,
sum(sum(sol.price_subtotal - (CASE WHEN sol.account_cost_amount != 0 THEN sol.account_cost_amount ELSE sol.purchase_price END ))) OVER  ( ORDER BY date_trunc('week', so.date_order)) as running_profit

FROM
sale_order as so
INNER JOIN sale_order_line as sol ON (sol.order_id = so.id)
INNER JOIN res_partner as rp ON (so.partner_id = rp.id)
WHERE EXISTS (
SELECT * FROM  res_partner_category_rel rpcl
WHERE 
rpcl.partner_id=rp.id and rpcl.category_id=37
AND so.date_order >= date_trunc('year', now())::timestamp::date
AND    so.date_order <  date_trunc('year', now() + '1 year'::interval)::timestamp::date 
and so.state != 'cancel'
)
GROUP BY
week
) as y
GROUP BY
id, week,week_profit
) as f1

何らかの理由で利益を週に分割せず、次のように 1 つの行の合計のみを表示します。

week    |week_profit|
20130114| 1500       |
4

1 に答える 1

4

積算合計の基本クエリ

よく知られている集計関数sum()ウィンドウ関数として使用します。

SELECT week, x.last_year_profit + y.running_profit AS week_profit
FROM (         -- total last year
   SELECT sum(profit) AS last_year_profit
   FROM   sale_order
   WHERE  date_order >= date_trunc('year', now() - interval '1 year')
   AND    date_order <  date_trunc('year', now()) 
   ) x
CROSS JOIN (   -- running sum current year
   SELECT date_trunc('week', date_order) AS week
         ,sum(sum(profit)) OVER (ORDER BY date_trunc('week', date_order))
                                                        AS running_profit
   FROM   sale_order
   WHERE  date_order >= date_trunc('year', now() - interval '1 year')
   AND    date_order <  date_trunc('year', now() + interval '1 year')
   GROUP  BY 1
   ) y;

結果:

week       | week_profit
-----------+------------
2012-01-02 | 1100
2012-01-09 | 1300
2012-01-16 | 1200
...

ここでの高度な機能は、単一のクエリ レベルでウィンドウ関数と集計関数SELECTを組み合わせることです。単一の式 (!) であっても、この項目が得られます。無実の目には驚くかもしれません。

sum(sum(profit)) OVER (ORDER BY date_trunc('week', date_order))

この密接に関連した回答で、これがどのように機能するかについての詳細な説明を見つけてください:
Postgres window function and group by exceptions

また、クエリで改善した他の複数の詳細にも注意してください。

->SQLfiddle

配列/クロス集計()

すべての週を 1 つの行に集計する原始的な方法は、結果を配列に集計することです。

SELECT ARRAY( 
    SELECT x.last_year_profit + y.running_profit  -- only one column
    FROM (
    -- rest like query above
   ) a

結果:

{1100,1300,1200, ...}

または、より高度な場合は、次のcrosstab()関連する回答で概説されているようなクエリを使用します:
PostgreSQL Crosstab Query

特に時間データを扱う、関連する多くのクロスバブの回答の1つ:
日付範囲によって分離された行数のクエリ

于 2013-06-10T17:46:56.290 に答える