| 9 | | WITH MonthlySales AS ( |
| 10 | | SELECT |
| 11 | | DATE_TRUNC('month', date_time) AS sales_month, |
| 12 | | SUM(total_amount) AS revenue |
| 13 | | FROM sale |
| 14 | | GROUP BY 1 |
| 15 | | ) |
| 16 | | SELECT |
| 17 | | sales_month, |
| 18 | | revenue AS current_month_revenue, |
| 19 | | LAG(revenue) OVER (ORDER BY sales_month) AS previous_month_revenue, |
| 20 | | ROUND(((revenue - LAG(revenue) OVER (ORDER BY sales_month)) / |
| 21 | | NULLIF(LAG(revenue) OVER (ORDER BY sales_month), 0)) * 100, 2) AS growth_percentage |
| 22 | | FROM MonthlySales; |
| | 8 | SELECT |
| | 9 | w.warehouse_id, |
| | 10 | w.name AS warehouse_name, |
| | 11 | SUM(ws.quantity_on_hand) AS total_units, |
| | 12 | SUM(ws.quantity_on_hand * p.unit_price) AS total_stock_value |
| | 13 | FROM warehouse_stock ws |
| | 14 | JOIN warehouse w ON ws.warehouse_id = w.warehouse_id |
| | 15 | JOIN product p ON ws.product_id = p.product_id |
| | 16 | GROUP BY w.warehouse_id, w.name |
| | 17 | ORDER BY total_stock_value DESC; |
| 30 | | Result ← π sales_month, |
| 31 | | revenue → current_month_revenue, |
| 32 | | LAG(revenue) → previous_month_revenue, |
| 33 | | ROUND(((revenue - LAG(revenue)) / NULLIF(LAG(revenue), 0)) × 100, 2) → growth_percentage |
| 34 | | (τ sales_month ASC (MonthlySales)) |
| | 22 | Цел: Прикажува кој производ носи најмногу приход. |
| | 23 | |
| | 24 | {{{#!sql |
| | 25 | SELECT |
| | 26 | p.product_id, |
| | 27 | p.name AS product_name, |
| | 28 | SUM(si.quantity) AS total_units_sold, |
| | 29 | SUM(si.quantity * si.unit_price_at_sale) AS total_revenue |
| | 30 | FROM sale_item si |
| | 31 | JOIN product p ON si.product_id = p.product_id |
| | 32 | GROUP BY p.product_id, p.name |
| | 33 | ORDER BY total_revenue DESC; |
| 44 | | SELECT |
| 45 | | p.name AS product_name, |
| 46 | | w.name AS warehouse_location, |
| 47 | | ws.quantity_on_hand, |
| 48 | | p.reorder_level, |
| 49 | | CASE |
| 50 | | WHEN ws.quantity_on_hand <= p.reorder_level THEN 'CRITICAL: REORDER' |
| 51 | | WHEN ws.quantity_on_hand <= p.reorder_level * 1.5 THEN 'WARNING: LOW' |
| 52 | | ELSE 'HEALTHY' |
| 53 | | END AS stock_status |
| 54 | | FROM product p |
| 55 | | JOIN warehouse_stock ws ON p.product_id = ws.product_id |
| 56 | | JOIN warehouse w ON ws.warehouse_id = w.warehouse_id; |
| | 41 | SELECT |
| | 42 | po.po_id, |
| | 43 | po.status, |
| | 44 | p.name AS product_name, |
| | 45 | poi.quantity AS ordered_quantity, |
| | 46 | poi.received_quantity, |
| | 47 | (poi.quantity - poi.received_quantity) AS pending_quantity |
| | 48 | FROM purchase_order po |
| | 49 | JOIN purchase_order_item poi ON po.po_id = poi.po_id |
| | 50 | JOIN product p ON poi.product_id = p.product_id |
| | 51 | ORDER BY po.po_id; |
| 65 | | Result ← π product.name → product_name, |
| 66 | | warehouse.name → warehouse_location, |
| 67 | | quantity_on_hand, |
| 68 | | reorder_level, |
| 69 | | CASE(quantity_on_hand ≤ reorder_level → 'CRITICAL: REORDER', |
| 70 | | quantity_on_hand ≤ reorder_level × 1.5 → 'WARNING: LOW', |
| 71 | | ELSE → 'HEALTHY') → stock_status |
| 72 | | (Temp2) |
| | 58 | {{{#!sql |
| | 59 | SELECT |
| | 60 | c.category_id, |
| | 61 | c.name AS category_name, |
| | 62 | SUM(si.quantity * si.unit_price_at_sale) AS total_category_revenue |
| | 63 | FROM sale_item si |
| | 64 | JOIN product p ON si.product_id = p.product_id |
| | 65 | JOIN category c ON p.category_id = c.category_id |
| | 66 | GROUP BY c.category_id, c.name |
| | 67 | ORDER BY total_category_revenue DESC; |
| 96 | | Result ← γ warehouse_id, name → warehouse_name, capacity → total_unit_capacity; |
| 97 | | SUM(quantity_on_hand) → units_in_stock, |
| 98 | | ROUND((SUM(quantity_on_hand) / capacity) × 100, 2) → occupancy_percentage |
| 99 | | (Temp1) |
| 100 | | }}} |
| 101 | | |
| 102 | | ---- |
| 103 | | |
| 104 | | == 7. Анализа на застојни производи == |
| 105 | | |
| 106 | | Ги прикажува производите што не се продале во последните 90 дена и само зафаќаат простор и капитал. |
| | 87 | Цел: Ги прикажува производите што не се продале во последните 90 дена и само зафаќаат простор. |
| 121 | | |
| 122 | | '''Релациона алгебра:''' |
| 123 | | {{{ |
| 124 | | Temp1 ← product ⨝ product_id=product_id warehouse_stock |
| 125 | | |
| 126 | | Temp2 ← Temp1 ⟕ product_id=product_id sale_item |
| 127 | | |
| 128 | | Temp3 ← Temp2 ⟕ sale_id=sale_id sale |
| 129 | | |
| 130 | | Temp4 ← γ product_id, name, sku, quantity_on_hand; |
| 131 | | MAX(date_time) → last_sold_date (Temp3) |
| 132 | | |
| 133 | | Result ← π name → product_name, sku, quantity_on_hand, |
| 134 | | COALESCE(last_sold_date::TEXT, 'NO SALES RECORDED') → last_sold_date |
| 135 | | (σ last_sold_date < CURRENT_DATE - 90 ∨ last_sold_date IS NULL (Temp4)) |
| 136 | | }}} |
| 137 | | |
| 138 | | |
| 139 | | ---- |
| 140 | | |
| 141 | | '''Релациона алгебра:''' |
| 142 | | {{{ |
| 143 | | Temp1 ← ρ si1 (sale_item) |
| 144 | | |
| 145 | | Temp2 ← ρ si2 (sale_item) |
| 146 | | |
| 147 | | Temp3 ← σ si1.sale_id = si2.sale_id ∧ si1.product_id < si2.product_id (Temp1 × Temp2) |
| 148 | | |
| 149 | | Temp4 ← Temp3 ⨝ si1.product_id = p1.product_id (ρ p1 (product)) |
| 150 | | |
| 151 | | Temp5 ← Temp4 ⨝ si2.product_id = p2.product_id (ρ p2 (product)) |
| 152 | | |
| 153 | | Temp6 ← γ p1.name → product_a, p2.name → product_b; |
| 154 | | COUNT(*) → pair_occurrence_count (Temp5) |
| 155 | | |
| 156 | | Result ← δ 10 (τ pair_occurrence_count DESC (Temp6)) |
| 157 | | }}} |
| 158 | | |
| 159 | | ---- |
| 160 | | |
| 161 | | '''Релациона алгебра:''' |
| 162 | | {{{ |
| 163 | | LatestCost(product_id) ← π product_id, unit_cost |
| 164 | | (δ 1 (τ po_id DESC (purchase_order_item))) |
| 165 | | |
| 166 | | Temp1 ← warehouse ⨝ warehouse_id=warehouse_id warehouse_stock |
| 167 | | |
| 168 | | Temp2 ← Temp1 ⨝ product_id=product_id LatestCost |
| 169 | | |
| 170 | | Result ← γ warehouse.name → warehouse_location; |
| 171 | | SUM(quantity_on_hand × unit_cost) → total_inventory_valuation_mkd |
| 172 | | (Temp2) |
| 173 | | }}} |
| 174 | | |
| 175 | | ---- |
| 176 | | |
| 177 | | '''Символи и операции:''' |
| 178 | | * π - проекција (SELECT) |
| 179 | | * σ - селекција (WHERE) |
| 180 | | * ⨝ - природен спој (JOIN) |
| 181 | | * ⟕ - left outer join (LEFT JOIN) |
| 182 | | * × - Декартов производ (CROSS JOIN) |
| 183 | | * γ - групирање (GROUP BY) |
| 184 | | * τ - сортирање (ORDER BY) |
| 185 | | * δ - лимит (LIMIT) |
| 186 | | * ρ - преименување (AS / alias) |
| 187 | | * ∧ - логичко И (AND) |
| 188 | | * ∨ - логичко ИЛИ (OR) |