WITH ROLLUP ve GROUPING
Giriş — Rapordaki Toplam Satırı
Excel'de bir pivot tablo oluşturduğunda, her grubun altında otomatik ara toplam ve en altta genel toplam satırı olur. SQL'de bunu WITH ROLLUP yapar.
🎯 Analoji: Bir mağaza zincirinin satış raporu düşün. Her şubenin satışları listeleniyor, ama raporun sonunda "TÜM ŞUBELER TOPLAMI" satırı da olmalı. WITH ROLLUP bu toplam satırını otomatik ekler.
WITH ROLLUP — Hiyerarşik Toplamlar
-- Şehir bazlı sipariş sayısı + GENEL TOPLAM
SELECT
COALESCE(city, 'GENEL TOPLAM') AS city,
COUNT(*) AS order_count,
ROUND(SUM(total_amount), 2) AS revenue
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
GROUP BY city WITH ROLLUP;+--------------+-------------+-----------+
| city | order_count | revenue |
+--------------+-------------+-----------+
| Ankara | 3 | 66219.96 |
| Antalya | 1 | 8999.99 |
| Bursa | 1 | 899.99 |
| İstanbul | 4 | 58349.95 |
| İzmir | 1 | 45299.98 |
| GENEL TOPLAM | 10 | 179769.87 |
+--------------+-------------+-----------+Son satır (GENEL TOPLAM) MySQL tarafından otomatik eklendi.
Çoklu Sütunla ROLLUP
-- Yıl → Ay hiyerarşisi ile ROLLUP
SELECT
COALESCE(CAST(YEAR(order_date) AS CHAR), 'TOPLAM') AS year,
COALESCE(CAST(MONTH(order_date) AS CHAR), 'Alt Toplam') AS month,
COUNT(*) AS orders,
ROUND(SUM(total_amount), 2) AS revenue
FROM orders
GROUP BY YEAR(order_date), MONTH(order_date) WITH ROLLUP;+--------+-----------+--------+-----------+
| year | month | orders | revenue |
+--------+-----------+--------+-----------+
| 2024 | 1 | 5 | 167449.93 |
| 2024 | 2 | 5 | 12319.94 |
| 2024 | Alt Toplam| 10 | 179769.87 | ← 2024 yılı toplamı
| TOPLAM | Alt Toplam| 10 | 179769.87 | ← Genel toplam
+--------+-----------+--------+-----------+ROLLUP sağdan sola hiyerarşik toplamlar oluşturur:
Önce her yıl-ay kombinasyonu
Sonra her yılın toplamı (ay = NULL)
En son genel toplam (yıl ve ay = NULL)
GROUPING() Fonksiyonu — ROLLUP Satırlarını Tanıma
ROLLUP'ın eklediği toplam satırlarında gruplama sütunu NULL olur. Ama verinin kendisi de NULL olabilir — nasıl ayırt ederiz?
-- GROUPING() fonksiyonu: ROLLUP tarafından eklenen NULL ise 1 döner
SELECT
CASE
WHEN GROUPING(city) = 1 THEN '*** GENEL TOPLAM ***'
ELSE COALESCE(city, 'Şehir Belirtilmemiş')
END AS city,
COUNT(*) AS order_count,
ROUND(SUM(total_amount), 2) AS revenue
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
GROUP BY city WITH ROLLUP;GROUPING(sütun) değerleri:
0= Normal grup satırı (gerçek veri)1= ROLLUP tarafından oluşturulan toplam satırı
Çok Sütunlu GROUPING
SELECT
CASE WHEN GROUPING(c.city) = 1 THEN 'TÜM ŞEHİRLER' ELSE c.city END AS city,
CASE WHEN GROUPING(o.status) = 1 THEN 'TÜM DURUMLAR' ELSE o.status END AS status,
COUNT(*) AS order_count,
ROUND(SUM(o.total_amount), 2) AS revenue
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
GROUP BY c.city, o.status WITH ROLLUP;ROLLUP vs Manuel UNION Toplam
ROLLUP olmadan aynı sonucu UNION ile de üretebilirsin ama daha zahmetli:
-- ❌ Manuel — 2 ayrı sorgu + UNION
SELECT city, COUNT(*) AS cnt, SUM(total_amount) AS rev
FROM orders o JOIN customers c ON o.customer_id = c.customer_id
GROUP BY city
UNION ALL
SELECT 'TOPLAM', COUNT(*), SUM(total_amount)
FROM orders;
-- ✅ WITH ROLLUP — tek sorgu, otomatik
SELECT COALESCE(city, 'TOPLAM') AS city, COUNT(*), ROUND(SUM(total_amount), 2)
FROM orders o JOIN customers c ON o.customer_id = c.customer_id
GROUP BY city WITH ROLLUP;Gerçek Dünya Örneği — Hiyerarşik Satış Raporu
-- Kategori → Ürün hiyerarşik satış raporu
SELECT
CASE
WHEN GROUPING(cat.category_name) = 1 THEN '=== GENEL TOPLAM ==='
WHEN GROUPING(p.product_name) = 1 THEN CONCAT('-- ', cat.category_name, ' Toplamı --')
ELSE p.product_name
END AS item,
COALESCE(SUM(oi.quantity), 0) AS units_sold,
ROUND(COALESCE(SUM(oi.quantity * oi.unit_price), 0), 2) AS revenue
FROM categories cat
LEFT JOIN products p ON cat.category_id = p.category_id
LEFT JOIN order_items oi ON p.product_id = oi.product_id
GROUP BY cat.category_name, p.product_name WITH ROLLUP
HAVING COALESCE(SUM(oi.quantity), 0) > 0 OR GROUPING(p.product_name) = 1;Sıkça Yapılan Hatalar
ROLLUP satırındaki NULL'u veri NULL'uyla karıştırmak: GROUPING() fonksiyonu ile ayırt et.
ORDER BY ile ROLLUP: MySQL'de
WITH ROLLUPkullanırkenORDER BYeklemek toplam satırların konumunu bozabilir. Dikkatli kullan.ROLLUP'ı her raporda kullanmak: Uygulama katmanında toplam hesaplamak çoğu zaman daha pratik. ROLLUP, doğrudan SQL raporları ve BI araçları için idealdir.
📝 PostgreSQL Notu: PostgreSQL'de ROLLUP, CUBE ve GROUPING SETS daha esnektir: ``
sql GROUP BY ROLLUP(city, status) -- Hiyerarşik GROUP BY CUBE(city, status) -- Tüm kombinasyonlar GROUP BY GROUPING SETS ((city), (status), ()) -- Belirli kombinasyonlar``
Özet
WITH ROLLUPGROUP BY sonuçlarına otomatik ara toplam ve genel toplam satırları eklerROLLUP sağdan sola hiyerarşik toplamlar oluşturur
GROUPING(sütun)fonksiyonu ROLLUP tarafından eklenen satırları (1) normal satırlardan (0) ayırt ederÇoklu sütunla ROLLUP, her hiyerarşi seviyesi için ara toplam üretir
Excel pivot tablo benzeri raporlar için çok kullanışlı
PostgreSQL'de CUBE ve GROUPING SETS ek esneklik sağlar
AI Asistan
Sorularını yanıtlamaya hazır