2017-03-06 9 views
0

私は請求書用のテーブルを持っており、何百万というデータがあります。私のテーブルには、請求書と顧客のための最初と最後の日付があります。私の目標は、請求書の月額平均価格を計算することです。たとえば、私が持っている:INVOICE_IDは(1月17日をincudingない)2017年1月1日から16日が2017年1月17日にあります1aある まず、請求書:たとえばORACLE(Varray&loop)の請求書の月額平均価格を計算する方法

CUSTOMER_ID  INVOICE_ID FIRST_DATE  LAST_DATE  AMOUNT_OF_INVOICE 
9876543   1a   1 Jan 2017  17 Jan 2017   32$ 
9876543   1b   17 Jan 2017  10 Feb 2017   72$ 
9876543   1c   10 Feb 2017  7 March 2017  100$ 
9876543   1d   7 March 2017 1 April 2017  25$ 
9870011   2a   1 Jan 2017  10 Jan 2017   18$ 
9870011   2b   10 Jan 2017  10 Feb 2017   62$ 
9870011   2c   10 Feb 2017  1 April 2017  50$ 


my target is: 

CUSTOMER_ID  MONTH   MONTHLY_AVERAGE_PRICE 
9876543   January 2017   77$     (=16x2+15x3) 
9876543   February 2017  103$    (=9x3+19x4) 
9876543   March 2017   49$     (=6x4+25x1) 
9870011   January 2017   62$     (=9x2+22x2) 
9870011   February 2017  37$     (=9x2+19x1) 
9870011   March 2017   31$     (=31x1) 

を私がすることによって77 $(=16x2+15x3)を計算します。請求書の価格は32 $です。したがって、1日の平均価格は32/16 = 2 $です。 2番目の請求書は1bで、2017年1月17日から2017年2月10日までの24日間です。したがって、1日あたりの平均消費量は3 $です。この請求書の1月分は15日間です(1月17日から1月31日まで1月31日まで)。全体として、1月の平均消費量は16x2 $ + 15x3 $ = 77 $です。

私は月にデータを格納するためにVARRAYを使用する必要があり、FIRST_DATELAST_DATEの間の日を見つけるためにループを使用しなければならないと思います。しかし、私はそれをすることができませんでした。それとも他にもあるのですか?

+0

どうすれば77ドルを得ることができますか? 。平均は何ですか(= 16.2 + 15.3)?あなたの質問は明確ではありません.. – scaisEdge

+0

ああ申し訳ありません。 INVOICE_IDが1aである最初の請求書は、2017年1月1日から2017年1月17日までの16日間です(1月17日は含まれません)。請求書の価格は32 $です。したがって、1日の平均価格は32/16 = 2 $です。 2番目の請求書は1bで、2017年1月17日から2017年2月10日までの24日間です。したがって、1日あたりの平均消費量は3 $です。この請求書の1月分は15日間です(1月17日から1月31日まで1月31日まで)。 1月平均消費量はすべて16.2 $ + 15.3 $ = 77 $です。今は明らかですか?そうでない場合は、私はもっと説明することができます..あなたの助けをありがとう – Abdullah

答えて

0

Oracleのクエリ

WITH month_invoices (c_id, i_id, first_date, last_date, month_start, month_end, amount) 
AS (
    SELECT customer_id, 
     invoice_id, 
     first_date, 
     last_date, 
     first_date, 
     LEAST(ADD_MONTHS(TRUNC(first_date, 'MM'), 1), last_date), 
     amount_of_invoice 
    FROM your_table 
UNION ALL 
    SELECT c_id, 
     i_id, 
     first_date, 
     last_date, 
     month_end, 
     LEAST(ADD_MONTHS(month_end, 1), last_date), 
     amount 
    FROM month_invoices 
    WHERE month_end < last_date 
) 
SELECT c_id AS customer_id, 
     TRUNC(month_start, 'MM') AS month, 
     SUM(amount * (month_end - month_start)/(last_date - first_date)) 
     AS average_monthly_price 
FROM month_invoices 
GROUP BY c_id, TRUNC(month_start, 'MM') 
ORDER BY customer_id, month; 

出力

CUSTOMER_ID MONTH  AVERAGE_MONTHLY_PRICE 
----------- ---------- --------------------- 
    9876543 2017-01-01     77 
    9876543 2017-02-01     103 
    9876543 2017-03-01     49 
    9870011 2017-01-01     62 
    9870011 2017-02-01     37 
    9870011 2017-03-01     31 
+0

ありがとう。このコードは素晴らしいです:)私は理解を求めています。私は一部理解することはできません:UNIONをALL SELECT C_ID、 I_ID、 first_date、 LAST_DATE、 month_end、 LEAST(ADD_MONTHS(month_end、1)、LAST_DATE)、 量 month_invoices FROM WHERE month_end Abdullah

+0

@Abdullah再帰的サブクエリの因数分解句(再帰的CTEとも呼ばれます)です。 'SELECT ... FROM your_table'の最初の部分は、元のテーブルの各行の最初の月のデータを生成し、2番目の部分' UNION ALL SELECT ... FROM month_invoices'を繰り返して、各行の残りの月を生成します。元のテーブル。最後のビット 'SELECT ... FROM month_invoices GROUP BY ... 'は、それを毎月合計します。 – MT0

+0

ありがとうございました。これは私にとって素晴らしい情報でした。ありがとうございました – Abdullah

0

これは私が思い付いたものです。
内側のクエリは、各請求書の各日の行を作成します。
外部クエリはそれらを合計します。
請求書の最大期間は999日であることが前提です。

select customer_id, month, sum(average_cost_per_day) average_cost_per_day 
from (
    select max(customer_id) customer_id, 
     invoice_id, 
     to_char(first_date + n-1, 'MONTH YYYY') month, 
     count(1)*max(amount_of_invoice)/max(last_date-first_date) average_cost_per_day 
    from your_table 
    inner join (
    select level n 
    from dual 
    connect by level <= 1000 
) 
    on (first_date + n-1 < last_date) 
    group by invoice_id, to_char(first_date + n-1, 'MONTH YYYY') 
) 
group by customer_id, month 
order by customer_id desc, to_date(month,'MONTH YYYY'); 
関連する問題