Changes between Initial Version and Version 1 of AdvancedReport14


Ignore:
Timestamp:
09/25/26 16:23:53 (5 days ago)
Author:
201178
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedReport14

    v1 v1  
     1= Прогноза за идни приходи врз основа на тренд и сезонност =
     2
     3== Опис ==
     4
     5Извештајот ја пресметува прогнозата за приход во следните 3 месеци користејќи: (1) линеарен тренд од постоечките месечни податоци, (2) сезонски индекс по месец, (3) комбинирана прогноза. Користи прозорски функции, регресиони функции (REGR_SLOPE, REGR_INTERCEPT) и generate_series за генерирање на идни месеци. Доколку нема доволно месеци за сезонски индекс, се користи неутрална вредност 1.
     6
     7== SQL решение ==
     8
     9{{{
     10CREATE OR REPLACE FUNCTION project.get_revenue_forecast()
     11RETURNS TABLE (
     12    forecast_month TEXT,
     13    base_trend NUMERIC,
     14    seasonal_index NUMERIC,
     15    forecast_revenue NUMERIC,
     16    confidence TEXT
     17)
     18LANGUAGE sql
     19AS $$
     20    WITH monthly AS (
     21        SELECT
     22            DATE_TRUNC('month', p.payment_date) AS m,
     23            EXTRACT(MONTH FROM p.payment_date)::INT AS mo,
     24            SUM(p.amount)::numeric AS rev,
     25            ROW_NUMBER() OVER (ORDER BY DATE_TRUNC('month', p.payment_date)) AS month_idx
     26        FROM project.payment p
     27        JOIN project.orders o ON o.order_id = p.order_id
     28        WHERE o.status = 'ПЛАТЕНА'
     29        GROUP BY 1, 2
     30    ),
     31    trend AS (
     32        SELECT
     33            COALESCE(REGR_SLOPE(rev, month_idx), 0)::numeric AS slope,
     34            COALESCE(REGR_INTERCEPT(rev, month_idx), AVG(rev))::numeric AS intercept,
     35            COALESCE(AVG(rev), 0)::numeric AS avg_rev,
     36            COALESCE(STDDEV(rev), 0)::numeric AS stddev_rev,
     37            MAX(month_idx) AS last_idx
     38        FROM monthly
     39    ),
     40    seasonal AS (
     41        SELECT
     42            mo,
     43            AVG(rev)::numeric AS month_avg,
     44            (SELECT AVG(rev)::numeric FROM monthly) AS overall_avg
     45        FROM monthly
     46        GROUP BY mo
     47    ),
     48    forecast AS (
     49        SELECT
     50            gs.n AS month_offset,
     51            TO_CHAR(NOW() + (gs.n || ' months')::INTERVAL, 'YYYY-MM') AS fm,
     52            EXTRACT(MONTH FROM NOW() + (gs.n || ' months')::INTERVAL)::INT AS fmo
     53        FROM generate_series(1, 3) gs(n)
     54    )
     55    SELECT
     56        f.fm,
     57        ROUND((t.intercept + t.slope * (t.last_idx + f.month_offset))::numeric, 2),
     58        ROUND(COALESCE(s.month_avg / NULLIF(s.overall_avg, 0), 1)::numeric, 3),
     59        ROUND(GREATEST(
     60            (t.intercept + t.slope * (t.last_idx + f.month_offset))
     61            * COALESCE(s.month_avg / NULLIF(s.overall_avg, 0), 1),
     62            0
     63        )::numeric, 2),
     64        CASE
     65            WHEN t.avg_rev = 0 THEN 'НИСКА'
     66            WHEN t.stddev_rev / t.avg_rev < 0.2 THEN 'ВИСОКА'
     67            WHEN t.stddev_rev / t.avg_rev < 0.4 THEN 'СРЕДНА'
     68            ELSE 'НИСКА'
     69        END::TEXT
     70    FROM forecast f
     71    CROSS JOIN trend t
     72    LEFT JOIN seasonal s ON s.mo = f.fmo
     73    ORDER BY 1;
     74$$;
     75}}}
     76
     77== Релациона алгебра ==
     78
     79{{{
     80P(payment_id, order_id, amount, payment_date)
     81O(order_id, status)
     82
     83J1 ← P ⨝ P.order_id = O.order_id O
     84F1 ← σ status='ПЛАТЕНА' (J1)
     85
     86G1 ← γ m, mo; SUM(amount) → rev, ROW_NUMBER() → month_idx (F1)
     87
     88A1 ← α REGR_SLOPE(rev, month_idx) → slope,
     89        REGR_INTERCEPT(rev, month_idx) → intercept,
     90        AVG(rev) → avg_rev,
     91        STDDEV(rev) → stddev_rev,
     92        MAX(month_idx) → last_idx (G1)
     93
     94G2 ← γ mo; AVG(rev) → month_avg (G1)
     95A2 ← α AVG(rev) → overall_avg (G1)
     96S ← G2 ⨝ (G2.month_avg / A2.overall_avg) → seasonal_index
     97
     98GS ← generate_series(1, 3) → month_offset
     99J2 ← GS ⟕ S ON S.mo = MONTH(NOW() + month_offset months)
     100
     101R ← π forecast_month, base_trend, seasonal_index, forecast_revenue, confidence
     102      ( A1 × J2 )
     103
     104R_final ← τ forecast_month ASC (R)
     105}}}