PostgreSQL اینٹی پیٹرنز: "صرف ایک ہی ہونا چاہیے!"

ایس کیو ایل میں، آپ بیان کرتے ہیں کہ آپ "کیا" حاصل کرنا چاہتے ہیں، نہ کہ "کیسے" اس پر عمل کیا جانا چاہیے۔ لہذا، "جیسا کہ یہ سنا جاتا ہے کہ یہ کیسے لکھا جاتا ہے" کے انداز میں ایس کیو ایل کے سوالات تیار کرنے کا مسئلہ اپنی عزت کی جگہ لے لیتا ہے۔ ایس کیو ایل میں حالات کا حساب لگانے کی خصوصیات.

آج، انتہائی آسان مثالوں کا استعمال کرتے ہوئے، آئیے دیکھتے ہیں کہ استعمال کے تناظر میں اس سے کیا ہو سکتا ہے۔ GROUP/DISTINCT и LIMIT ان کے ساتھ.

اب اگر آپ نے درخواست میں لکھا "پہلے ان نشانیوں کو جوڑیں، اور پھر تمام نقلیں نکال دیں، صرف ایک باقی رہنا چاہئے ہر کلید کے لیے کاپی" - یہ بالکل اسی طرح کام کرے گا، یہاں تک کہ اگر کنکشن کی ضرورت ہی نہیں تھی۔

اور بعض اوقات آپ خوش قسمت ہوتے ہیں اور یہ "صرف کام کرتا ہے"، کبھی کبھی اس کا کارکردگی پر ناخوشگوار اثر پڑتا ہے، اور بعض اوقات یہ ایسے اثرات دیتا ہے جو ڈویلپر کے نقطہ نظر سے بالکل غیر متوقع ہوتے ہیں۔

PostgreSQL اینٹی پیٹرنز: "صرف ایک ہی ہونا چاہیے!"
ٹھیک ہے، شاید اتنا شاندار نہیں، لیکن ...

"سویٹ جوڑے": شامل ہوں + الگ

SELECT DISTINCT
  X.*
FROM
  X
JOIN
  Y
    ON Y.fk = X.pk
WHERE
  Y.bool_condition;

واضح ہو جائے گا کہ وہ کیا چاہتے ہیں۔ ایسے ریکارڈز X کو منتخب کریں جن کے لیے Y میں ایسے ریکارڈ موجود ہیں جو پوری ہونے والی شرط سے متعلق ہیں۔. کے ذریعے ایک درخواست لکھی۔ JOIN - کئی بار کچھ pk اقدار حاصل کیں (بالکل کتنی مناسب اندراجات Y میں ظاہر ہوئیں)۔ کیسے ہٹائیں؟ یقیناً DISTINCT!

یہ خاص طور پر "اطمینان بخش" ہے جب ہر X-ریکارڈ کے لیے کئی سو متعلقہ Y-ریکارڈز ہوتے ہیں، اور پھر ڈپلیکیٹس کو بہادری سے ہٹا دیا جاتا ہے...

PostgreSQL اینٹی پیٹرنز: "صرف ایک ہی ہونا چاہیے!"

کیسے ٹھیک کریں؟ شروع کرنے کے لیے، اس بات کا احساس کریں کہ مسئلہ میں ترمیم کی جا سکتی ہے۔ "ایسے ریکارڈز کو منتخب کریں جن کے لیے Y میں کم از کم ایک پوری شرط سے وابستہ ہے" - آخرکار، ہمیں خود Y-ریکارڈ سے کسی چیز کی ضرورت نہیں ہے۔

نیسٹڈ موجود ہے۔

SELECT
  *
FROM
  X
WHERE
  EXISTS(
    SELECT
      NULL
    FROM
      Y
    WHERE
      fk = X.pk AND
      bool_condition
    LIMIT 1
  );

PostgreSQL کے کچھ ورژن سمجھتے ہیں کہ EXISTS میں سامنے آنے والی پہلی انٹری کو تلاش کرنا کافی ہے، پرانے والے ایسا نہیں کرتے۔ اس لیے میں ہمیشہ اشارہ کرنے کو ترجیح دیتا ہوں۔ LIMIT 1 اندر EXISTS.

لیٹرل جوائن

SELECT
  X.*
FROM
  X
, LATERAL (
    SELECT
      Y.*
    FROM
      Y
    WHERE
      fk = X.pk AND
      bool_condition
    LIMIT 1
  ) Y
WHERE
  Y IS DISTINCT FROM NULL;

یہی آپشن، اگر ضروری ہو تو، ملنے والے متعلقہ Y-ریکارڈ سے فوری طور پر کچھ ڈیٹا واپس کرنے کی اجازت دیتا ہے۔ اسی طرح کے اختیار پر مضمون میں بحث کی گئی ہے۔ "پوسٹگری ایس کیو ایل اینٹی پیٹرنز: ایک نایاب ریکارڈ جوائن کے وسط تک پہنچ جائے گا".

"مزید ادائیگی کیوں کریں": DISTINCT [ON] + LIMIT 1

اس طرح کے سوالات کی تبدیلیوں کا ایک اضافی فائدہ یہ ہے کہ ریکارڈز کی تلاش کو آسانی سے محدود کرنے کی صلاحیت اگر ان میں سے صرف ایک یا چند کی ضرورت ہو، جیسا کہ درج ذیل صورت میں:

SELECT DISTINCT ON(X.pk)
  *
FROM
  X
JOIN
  Y
    ON Y.fk = X.pk
LIMIT 1;

اب ہم درخواست کو پڑھتے ہیں اور یہ سمجھنے کی کوشش کرتے ہیں کہ DBMS کو کیا کرنے کی تجویز ہے:

  • علامات کو جوڑنا
  • X.pk کے ذریعے منفرد
  • باقی اندراجات میں سے، ایک کو منتخب کریں۔

تو آپ کو کیا ملا؟ "صرف ایک اندراج" انوکھے سے - اور اگر ہم اسے غیر منفرد میں سے لے لیں تو کیا نتیجہ کسی طرح بدل جائے گا؟.. "اور اگر کوئی فرق نہیں ہے تو زیادہ ادائیگی کیوں؟"

SELECT
  *
FROM
  (
    SELECT
      *
    FROM
      X
    -- сюда можно подсунуть подходящих условий
    LIMIT 1 -- +1 Limit
  ) X
JOIN
  Y
    ON Y.fk = X.pk
LIMIT 1;

اور بالکل اسی موضوع کے ساتھ GROUP BY + LIMIT 1.

"مجھے صرف پوچھنا ہے": مضمر گروپ + LIMIT

اسی طرح کی چیزیں مختلف جگہوں پر ہوتی ہیں۔ غیر خالی پن کی جانچ پڑتال درخواست کے آگے بڑھتے ہی نشانیاں یا CTEs:

...
CASE
  WHEN (
    SELECT
      count(*)
    FROM
      X
    LIMIT 1
  ) = 0 THEN ...

مجموعی افعال (count/min/max/sum/...) کو پورے سیٹ پر کامیابی سے عمل میں لایا جاتا ہے، یہاں تک کہ واضح ہدایات کے بغیر GROUP BY. صرف کے ساتھ LIMIT وہ بہت دوستانہ نہیں ہیں.

ڈویلپر سوچ سکتا ہے۔ "اگر وہاں ریکارڈ موجود ہیں تو مجھے LIMIT سے زیادہ کی ضرورت نہیں ہے". لیکن ایسا مت کرو! کیونکہ بنیاد کے لئے یہ ہے:

  • وہ کیا چاہتے ہیں شمار کریں تمام ریکارڈ کے مطابق
  • جتنی لائنیں مانگیں دیں

ہدف کی شرائط پر منحصر ہے، درج ذیل متبادلات میں سے ایک بنانا مناسب ہے:

  • (count + LIMIT 1) = 0 پر NOT EXISTS(LIMIT 1)
  • (count + LIMIT 1) > 0 پر EXISTS(LIMIT 1)
  • count >= N پر (SELECT count(*) FROM (... LIMIT N))

"گرام میں کتنا لٹکانا ہے": DISTINCT + LIMIT

SELECT DISTINCT
  pk
FROM
  X
LIMIT $1

ایک بولی ڈویلپر خلوص دل سے یقین کر سکتا ہے کہ درخواست پر عمل درآمد بند ہو جائے گا۔ جیسے ہی ہمیں پہلی مختلف قدروں میں سے $1 ملے جو سامنے آئیں.

مستقبل میں کسی وقت یہ ایک نئے نوڈ کی بدولت کام کر سکتا ہے اور کرے گا۔ انڈیکس اسکیپ اسکینجس کے نفاذ پر فی الحال کام ہو رہا ہے، لیکن ابھی تک نہیں۔

فی الحال پہلے تمام ریکارڈ حاصل کر لیا جائے گا۔, منفرد ہیں، اور صرف ان سے درخواست کی گئی رقم واپس کی جائے گی۔ یہ خاص طور پر افسوسناک ہے اگر ہم کچھ ایسا چاہتے ہیں۔ $ 1 = 4، اور ٹیبل میں سیکڑوں ہزاروں ریکارڈ موجود ہیں ...

بیکار میں اداس نہ ہونے کے لیے، آئیے ایک بار بار چلنے والی استفسار کا استعمال کریں۔ PostgreSQL Wiki سے "DISTINCT غریبوں کے لیے ہے":

PostgreSQL اینٹی پیٹرنز: "صرف ایک ہی ہونا چاہیے!"

ماخذ: www.habr.com

نیا تبصرہ شامل کریں