
مالیاتی ڈیٹا ویئر ہاؤسز کے لیے SQL
منظم مالیاتی ڈیٹا کو کیوری، اکٹھا، اور تجزیہ کریں
SQL مالیاتی ڈیٹا کی زبان کیوں ہے
ہر ٹریڈ، ہر ٹِک، ہر آرڈر بک اپڈیٹ — مالیاتی مارکیٹس ساختہ ڈیٹا کی حیران کن مقدار پیدا کرتی ہیں۔ اور چار دہائیوں سے زیادہ عرصے سے، SQL (Structured Query Language) اس ڈیٹا کو کوئری کرنے، تبدیل کرنے اور تجزیہ کرنے کا غالب ٹول رہا ہے۔ یہ چمکدار نہیں ہے۔ یہ ٹرینڈی نہیں ہے۔ مگر جب کوئی پورٹ فولیو مینیجر پوچھتا ہے "پچھلے منگل دن 2 سے 3 بجے UTC کے درمیان ETH ٹریڈز پر میری اوسط فل قیمت کیا تھی؟"، جواب SQL سے آتا ہے۔
مالیاتی ڈیٹا فطری طور پر ریلیشنل ہوتا ہے۔ ایک ٹریڈ کسی آرڈر کا حوالہ دیتا ہے، جو کسی اکاؤنٹ کا حوالہ دیتا ہے، جو کسی صارف کا ہوتا ہے۔ پوزیشنز انسٹرومنٹس سے متعلق ہوتی ہیں؛ انسٹرومنٹس مارکیٹس سے متعلق ہوتے ہیں۔ ریلیشنل ماڈل — رو اور کالمز والے ٹیبلز، فارن کیز سے جڑے ہوئے — ان تعلقات پر فطری طور پر منطبق ہوتا ہے۔ یہی وجہ ہے کہ PostgreSQL، MySQL، اور SQL Server جیسے ریلیشنل ڈیٹابیس مالیاتی انفراسٹرکچر کی ستون رہتے ہیں، Goldman Sachs سے GaiaEx تک۔
SQL کی طاقت اس کی declarative فطرت میں ہے: آپ بتاتے ہیں کیا چاہیے، کیسے حاصل کرنا ہے یہ نہیں۔ ڈیٹابیس انجن بہترین ایگزیکیوشن پلان خود نکالتا ہے۔ یہ اس وقت بہت اہم ہو جاتا ہے جب آپ کے ٹریڈ ہسٹری ٹیبل میں 500 ملین رَوز ہوں اور آپ کو ایک سیکنڈ سے کم میں نتائج درکار ہوں۔ صحیح کوئری لکھیں، صحیح انڈیکس بنائیں، اور SQL ڈیلیور کرتا ہے — چاہے آپ اسے کسی لوکل PostgreSQL انسٹنس یا کلاؤڈ-اسکیل ڈیٹا ویئر ہاؤس کے مقابلے میں چلا رہے ہوں۔
SELECT، JOIN، اور WHERE: ٹریڈ ڈیٹا کو کوئری کرنا
آئیے ایک ٹھوس اسکیما سے شروع کرتے ہیں۔ تصور کریں کہ GaiaEx جیسے پلیٹ فارم پر trades ٹیبل ہے:
CREATE TABLE trades (
trade_id BIGINT PRIMARY KEY,
user_id INT NOT NULL,
symbol VARCHAR(20) NOT NULL,
side VARCHAR(4) NOT NULL, -- 'buy' or 'sell'
price NUMERIC(18,8) NOT NULL,
quantity NUMERIC(18,8) NOT NULL,
fee NUMERIC(18,8) DEFAULT 0,
executed_at TIMESTAMPTZ NOT NULL
);
سب سے بنیادی آپریشن فلٹرنگ کے ساتھ SELECT اسٹیٹمنٹ ہے۔ پچھلے 24 گھنٹوں میں $3,000 سے زیادہ کی تمام ETH-USD خرید ٹریڈز تلاش کرنے کے لیے:
SELECT trade_id, price, quantity, executed_at
FROM trades
WHERE symbol = 'ETH-USD'
AND side = 'buy'
AND price > 3000
AND executed_at > NOW() - INTERVAL '24 hours'
ORDER BY executed_at DESC;
JOINs متعلقہ ٹیبلز کو جوڑتے ہیں۔ فرض کریں آپ کے پاس accounts ٹیبل ہے اور آپ فی اکاؤنٹ ٹیئر ٹریڈنگ والیوم دیکھنا چاہتے ہیں:
SELECT a.tier, COUNT(*) AS trade_count,
SUM(t.price * t.quantity) AS total_volume
FROM trades t
JOIN accounts a ON t.user_id = a.user_id
WHERE t.executed_at > NOW() - INTERVAL '30 days'
GROUP BY a.tier
ORDER BY total_volume DESC;
یہ کوئریز مالیاتی تجزیہ کاروں، رسک ٹیموں، اور کمپلائنس آفیسرز کی روزمرہ ضروریات ہیں۔ ان پر عبور حاصل کریں اور آپ اپنے ڈیٹا کے اندر موجود کوئی بھی سوال جواب دے سکتے ہیں۔
ونڈو فنکشنز: تجزیہ کار کا خفیہ اسلحہ
ونڈو فنکشنز وہ چیز ہیں جو مالیات میں SQL کے ابتدائی سیکھنے والوں کو SQL کے ماہرین سے الگ کرتی ہیں۔ یہ آپ کو موجودہ رَو سے متعلق رَوز کے ایک سیٹ پر حساب کرنے دیتی ہیں — بغیر نتیجے کو ایک واحد مجموعی ویلیو میں سکیڑے۔ انہیں اپنے ڈیٹا پر "چلتی ہوئی حسابات" سمجھیں۔
مالیاتی تجزیے میں سب سے زیادہ استعمال ہونے والے ونڈو فنکشنز:
- ROW_NUMBER() — ایک پارٹیشن کے اندر ہر رَو کو ایک ترتیب وار نمبر دیتا ہے۔ ڈی-ڈپلیکیشن یا فی سمبل Nویں ٹریڈ منتخب کرنے کے لیے مفید۔
- LAG() اور LEAD() — پچھلی یا اگلی رَو کی ویلیو تک رسائی۔ ٹریڈ-سے-ٹریڈ ریٹرنز کا حساب لگانے یا ٹائم-سیریز ڈیٹا میں خالی جگہیں تلاش کرنے کے لیے ضروری۔
- SUM() OVER () — چلتے کل حساب۔ مجموعی والیوم، مجموعی P&L، یا چلتی پوزیشن سائز کا حساب لگائیں۔
- AVG() OVER (ROWS BETWEEN) — SQL میں براہِ راست موونگ ایوریجز۔ Python کی ضرورت نہیں۔
یہاں ایک عملی مثال ہے — BTC کے لیے ٹریڈ-سے-ٹریڈ قیمت میں تبدیلی اور ایک چلتی پوزیشن کا حساب لگانا:
SELECT executed_at, price, quantity, side,
price - LAG(price) OVER (ORDER BY executed_at) AS price_change,
SUM(CASE WHEN side = 'buy' THEN quantity ELSE -quantity END)
OVER (ORDER BY executed_at) AS running_position
FROM trades
WHERE symbol = 'BTC-USD'
ORDER BY executed_at;
ونڈو فنکشنز آپ کی رَو کی تعداد کم نہیں کرتی — GROUP BY کے برعکس، ہر ان پُٹ رَو ایک آؤٹ پُٹ رَو پیدا کرتی ہے۔ یہ انہیں تفصیلی ٹریڈ لاگز میں تجزیاتی کالمز شامل کرنے کے لیے کامل بناتا ہے بغیر بلک ختم ہوئے۔ انہیں اپنے ڈیٹا کو "خلاصہ" کرنے کے بجائے "مالا مال" کرنا سمجھیں۔
OHLCV ایگریگیشن کے لیے — کینڈل اسٹک چارٹس کی بنیاد — آپ GROUP BY کو ٹائم-بکٹنگ اور معیاری ایگریگیٹس کے ساتھ ملا سکتے ہیں:
SELECT date_trunc('hour', executed_at) AS bucket,
(ARRAY_AGG(price ORDER BY executed_at))[1] AS open,
MAX(price) AS high,
MIN(price) AS low,
(ARRAY_AGG(price ORDER BY executed_at DESC))[1] AS close,
SUM(quantity) AS volume
FROM trades
WHERE symbol = 'ETH-USD'
GROUP BY bucket
ORDER BY bucket;CTEs: پیچیدہ تجزیاتی کوئریز کو ترتیب دینا
Common Table Expressions (CTEs) آپ کو ایک پیچیدہ کوئری کو نام یافتہ، قابلِ مطالعہ مراحل میں توڑنے دیتی ہیں — پروگرامنگ میں فنکشنز کی طرح۔ یہ WITH کیورڈ سے متعارف کروائی جاتی ہیں اور یہ ایک دوسرے کا حوالہ ترتیب وار دے سکتی ہیں۔
فرض کریں آپ اپنے 10 سب سے زیادہ منافع بخش ٹریڈنگ دنوں کی شناخت کرنا چاہتے ہیں، مگر منافع بخشی کا حساب فیس شامل کر کے فی دن نیٹ P&L کے حساب سے ہونا چاہیے۔ CTEs کے ساتھ، آپ اسے مرحلہ وار بنا سکتے ہیں:
WITH daily_trades AS (
SELECT DATE(executed_at) AS trade_date,
SUM(CASE WHEN side = 'sell' THEN price * quantity
ELSE -price * quantity END) AS gross_pnl,
SUM(fee) AS total_fees
FROM trades
WHERE user_id = 42
GROUP BY DATE(executed_at)
),
daily_pnl AS (
SELECT trade_date,
gross_pnl - total_fees AS net_pnl,
SUM(gross_pnl - total_fees) OVER (ORDER BY trade_date) AS cumulative_pnl
FROM daily_trades
)
SELECT trade_date, net_pnl, cumulative_pnl
FROM daily_pnl
ORDER BY net_pnl DESC
LIMIT 10;
ہر CTE ایک پیراگراف کی طرح پڑھی جاتی ہے۔ daily_trades خام ٹریڈز کو روزانہ خلاصوں میں جمع کرتی ہے۔ daily_pnl نیٹ P&L اور ایک چلتی کل حساب لگاتی ہے۔ آخری SELECT سب سے اوپر کے 10 دن منتخب کرتی ہے۔ اسے ایک واحد بڑی سب-کوئری سے مقابلہ کریں — CTE ورژن قابلِ برقرار، قابلِ ٹیسٹ، اور خود-وضاحتی ہے۔
پروڈکشن مالیاتی نظاموں میں، CTEs ہر چیز کے لیے استعمال ہوتی ہیں، ریگولیٹری رپورٹنگ (اکاؤنٹس میں مارجن کی ضروریات کو جمع کرنا) سے حقیقی وقت کے ڈیش بورڈ کوئریز تک (GaiaEx پر رولنگ 24-گھنٹے والیوم کا حساب لگانا)۔ یہ اسی طرح ترتیب پاتی ہیں جیسے اچھی طرح تشکیل شدہ کوڈ ترتیب پاتا ہے — ہر لیئر پچھلی پر تعمیر ہوتی ہے۔
ٹائم-سیریز کارکردگی کے لیے انڈیکسنگ اور پارٹیشننگ
کوئری صرف اتنی تیز ہوتی ہے جتنا انڈیکس جو اسے سپورٹ کرتا ہے۔ صحیح انڈیکس کے بغیر، ایک سادہ WHERE شرط بھی سیکوینشل اسکین پر مجبور کرتی ہے — ٹیبل کی ہر رَو پڑھنا۔ 500 ملین رَوز پر، یہ منٹوں کی بات ہو جاتی ہے ملی سیکنڈز کے بجائے۔
مالیاتی ٹائم-سیریز ڈیٹا کے لیے، سب سے اہم انڈیکس پیٹرن (symbol, executed_at) پر کمپوزٹ B-ٹری انڈیکس ہے:
CREATE INDEX idx_trades_symbol_time
ON trades (symbol, executed_at DESC);
یہ ایک واحد انڈیکس زیادہ تر تجزیاتی کوئریز کو تیز کرتا ہے: "پچھلے گھنٹے کی تمام ETH ٹریڈز"، "دو ٹائم اسٹیمپس کے درمیان BTC ٹریڈز"، یا "فی سمبل تازہ ترین ٹریڈ"۔ کالم کی ترتیب اہم ہے — symbol پہلے مساوی فلٹرنگ فعال کرتا ہے، پھر executed_at انڈیکس کے اس پارٹیشن کے اندر موثر رینج اسکینز فعال کرتا ہے۔
ایسے ٹیبلز کے لیے جو سیکڑوں ملین رَوز سے بڑھ جائیں، ٹیبل پارٹیشننگ لازمی ہے۔ PostgreSQL رینج کے حساب سے declarative پارٹیشننگ سپورٹ کرتا ہے — ٹائم-سیریز کے لیے مثالی:
CREATE TABLE trades (
trade_id BIGINT, symbol VARCHAR(20),
price NUMERIC(18,8), executed_at TIMESTAMPTZ
) PARTITION BY RANGE (executed_at);
CREATE TABLE trades_2026_q1 PARTITION OF trades
FOR VALUES FROM ('2026-01-01') TO ('2026-04-01');
CREATE TABLE trades_2026_q2 PARTITION OF trades
FOR VALUES FROM ('2026-04-01') TO ('2026-07-01');
پارٹیشننگ کے ساتھ، مارچ 2026 کے ڈیٹا کے لیے ایک کوئری صرف Q1 پارٹیشن اسکین کرتی ہے — انجن Q2، Q3، اور Q4 کو مکمل طور پر چھوڑ دیتا ہے۔ یہ تکنیک، جسے پارٹیشن پروننگ کہا جاتا ہے، بڑے تاریخی ڈیٹا سیٹس پر شدت کے درجے کی رفتار بڑھاتی ہے۔
PostgreSQL بمقابلہ ClickHouse بمقابلہ BigQuery: صحیح انجن منتخب کرنا
تمام ڈیٹابیس مالیاتی اینالیٹکس کو یکساں طریقے سے نہیں سنبھالتے۔ انتخاب آپ کے کوئری پیٹرنز، ڈیٹا حجم، اور تاخیر کی ضروریات پر منحصر ہے۔
PostgreSQL اصل مزدور ہے۔ یہ ٹرانزیکشنل ورک لوڈز میں مہارت رکھتا ہے (حقیقی وقت میں ٹریڈز ریکارڈ کرنا)، ACID گارنٹیز سپورٹ کرتا ہے، پیچیدہ JOINs کو خوش اسلوبی سے سنبھالتا ہے، اور مناسب انڈیکسنگ اور پارٹیشننگ کے ساتھ سیکڑوں ملین رَوز تک اسکیل کرتا ہے۔ یہ آپریشنل ڈیٹابیسز — ریکارڈ کے نظام — کے لیے صحیح انتخاب ہے۔ مثال کے طور پر، GaiaEx اپنے بنیادی ٹریڈنگ ڈیٹا کے لیے PostgreSQL-مطابق انفراسٹرکچر پر انحصار کرتا ہے، ان اعتماد کی گارنٹیز کے ساتھ جو مالیاتی نظام تقاضا کرتے ہیں۔
ClickHouse ایک کالمی (columnar) ڈیٹابیس ہے جو اربوں رَوز پر تجزیاتی کوئریز کے لیے ڈیزائن کیا گیا ہے۔ جہاں PostgreSQL ڈیٹا کو رَو-بہ-رَو محفوظ کرتا ہے (انفرادی ٹریڈز داخل کرنے کے لیے بہترین)، ClickHouse ڈیٹا کو کالم-بہ-کالم محفوظ کرتا ہے (ملینوں رَوز پر ایک واحد کالم کو جمع کرنے کے لیے بہترین)۔ "3 سالوں میں BTC کے لیے اوسط فی گھنٹہ والیوم" جیسی کوئری جو PostgreSQL میں 30 سیکنڈ لیتی ہے، ClickHouse میں 200 ملی سیکنڈز میں مکمل ہو سکتی ہے۔ سمجھوتہ: ClickHouse UPDATE یا DELETE کو مؤثر طریقے سے سپورٹ نہیں کرتا — یہ ڈیزائن کے مطابق صرف-اضافہ (append-only) ہے۔
BigQuery (Google Cloud) ایک سرور-لیس کالمی ویئر ہاؤس ہے۔ کوئی انفراسٹرکچر منیج نہیں کرنا، فی-کوئری قیمت، اور پیٹا بائٹ-اسکیل صلاحیت۔ یہ ایڈ-ہاک اینالیٹکس، ریسرچ، اور تحقیق کے لیے مثالی ہے — مگر کوئری کی تاخیر سیکنڈز میں ماپی جاتی ہے، ملی سیکنڈز میں نہیں، جو اسے حقیقی وقت کی ایپلیکیشنز کے لیے نامناسب بناتی ہے۔
- حقیقی وقت میں ٹریڈ ریکارڈنگ اور آرڈر مینجمنٹ → PostgreSQL
- اربوں رَوز پر تاریخی اینالیٹکس اور بیک ٹیسٹنگ → ClickHouse
- ایڈ-ہاک تحقیق اور کراس-ٹیم ڈیٹا شیئرنگ → BigQuery
کئی پیشہ ور ٹریڈنگ فرمز تینوں کو ایک درجہ بندی شدہ آرکیٹیکچر میں استعمال کرتی ہیں: PostgreSQL بطور گرم آپریشنل اسٹور، ClickHouse بطور نیم گرم تجزیاتی لیئر، اور BigQuery بطور ٹھنڈا آرکائیو۔ اچھی SQL لکھنے کی مہارت ان سب میں منتقل ہوتی ہے — سنٹیکس 90% یکساں ہے، اور تجزیاتی سوچ 100% یکساں ہے۔