TATECHATLAS
◎ हिन्दी
डेटा और डेटाबेस

JOIN से पंक्तियाँ क्यों बढ़ती हैं: कुंजियाँ, संबंध और परिणाम का स्तर

मिलने वाली कुंजियों को गिनकर, सीमाएँ देखकर और परिणाम का सही स्तर चुनकर JOIN की दोहराई गई पंक्तियाँ समझें।

इस पृष्ठ पर

JOIN मेल खाने वाली पंक्तियों के जोड़े देता है। इसलिए एक मूल पंक्ति कई बार दिखाई दे सकती है और यह अपने आप में गलती नहीं है। पहले तय करें कि परिणाम की एक पंक्ति किसे दर्शाएगी: एक ऑर्डर, उसकी एक वस्तु या ऑर्डर का सारांश। फिर संबंधित फ़िल्टर लगाने के बाद दोनों तरफ वास्तविक जोड़ने वाली कुंजियों की आवृत्ति गिनें। किसी गैर-NULL कुंजी के बाईं तरफ L और दाईं तरफ R बार आने पर समानता वाला JOIN, L × R जोड़े देता है। आज का डेटा अनोखा होना भविष्य की अनोखापन सीमा का प्रमाण नहीं है।

JOIN वास्तव में क्या गिनता है

INNER JOIN में ON की शर्त पूरी करने वाला हर जोड़ा परिणाम की एक पंक्ति बनता है। बाहरी जोड़ बिना साथी वाली पंक्ति भी रख सकता है और दूसरी तरफ NULL भर सकता है। कार्तीय गुणनफल SQL का तार्किक अर्थ समझाता है; इसका मतलब यह नहीं कि डेटाबेस वास्तव में हर संभव जोड़ा बनाकर ही काम करेगा। पहले जोड़ की शर्त देखें, फिर बाकी क्वेरी। बाद में लगा WHERE फ़िल्टर जुड़ी हुई पंक्तियाँ हटा सकता है और अंतिम संख्या बदल सकता है।

कार्तीय गुणनफल और दोहराई गई कुंजियाँ

CROSS JOIN हर बाईं पंक्ति को हर दाईं पंक्ति से जोड़ता है। दोनों तरफ तीन पंक्तियाँ हों तो नौ जोड़े बनते हैं। समानता वाला जोड़ केवल समान कुंजी के जोड़े रखता है। एक कुंजी दोनों तरफ दोहराई जाए तो उसके जोड़ों की संख्या दोनों आवृत्तियों का गुणनफल होती है। इससे अनेक से अनेक संबंध में वृद्धि हो सकती है। केवल एक से अनेक संबंध होने का मतलब यह नहीं कि परिणाम सबसे बड़ी मूल तालिका से भी बड़ा होगा। वास्तविक मिलान की संख्या गिनना ज़रूरी है।

WITH t1(num) AS (VALUES (1), (2), (3)),
     t2(num) AS (VALUES (1), (3), (5))
SELECT t1.num AS left_num, t2.num AS right_num
FROM t1 CROSS JOIN t2;
-- Nine pairs in this illustrative dataset.

एक से अनेक संबंध का उदाहरण

उदाहरण में ऑर्डर 1 की दो वस्तुएँ हैं और ऑर्डर 2 की एक वस्तु है। जोड़ तीन पंक्तियाँ देता है। पहले ऑर्डर की पहचान दो बार आती है, लेकिन वस्तुओं की पहचान अलग है। ये उपयोगी संबंध हैं, जिन्हें गलत डुप्लिकेट मानकर हटाना जानकारी खो सकता है। यदि रिपोर्ट में हर वस्तु की एक पंक्ति चाहिए तो यही स्तर सही है। यदि हर ऑर्डर की एक पंक्ति चाहिए तो पहले वस्तुओं का सारांश बनाएँ या आवश्यक जानकारी पाने का दूसरा तरीका चुनें।

WITH orders(order_id) AS (VALUES (1), (2)),
     order_items(item_id, order_id) AS (VALUES (10, 1), (11, 1), (12, 2))
SELECT o.order_id, i.item_id
FROM orders AS o
JOIN order_items AS i ON i.order_id = o.order_id
ORDER BY o.order_id, i.item_id;
-- Three pairs: order 1 appears with two different items.

LEFT JOIN और बिना साथी वाली पंक्तियाँ

LEFT JOIN बिना मिलान वाली बाईं पंक्ति को रखता है और दाईं तरफ NULL देता है। कई मिलान हों तो वही बाईं पंक्ति फिर भी कई बार आती है। छोटे उदाहरण में कुंजियाँ 1 और 3 मिलती हैं, जबकि 2 का साथी नहीं है; कुल तीन पंक्तियाँ मिलती हैं। यह बाद के फ़िल्टर से पहले जोड़ का परिणाम है। दाएँ कॉलम पर WHERE की शर्त NULL वाली पंक्तियाँ निकाल सकती है। इसलिए केवल LEFT JOIN शब्द देखकर निष्कर्ष न निकालें, पूरी क्वेरी पढ़ें।

WITH t1(num) AS (VALUES (1), (2), (3)),
     t2(num) AS (VALUES (1), (3), (5))
SELECT t1.num AS left_num, t2.num AS right_num
FROM t1 LEFT JOIN t2 ON t1.num = t2.num
ORDER BY t1.num;
-- Three rows; the right value for left key 2 is NULL.

वास्तविक कुंजियों की आवृत्ति जाँचें

प्रासंगिक फ़िल्टर लगाने के बाद दोनों तरफ उस कुंजी की आवृत्ति गिनें जो वास्तव में जोड़ में प्रयोग हुई है। उदाहरण order_id के अनुसार वस्तुओं को समूहित करता है और दो वस्तुओं वाला ऑर्डर दिखाता है। सामान्य समानता के मिलान का कारण खोजते समय NULL कुंजियाँ अलग करें, क्योंकि इस शर्त में NULL दूसरे NULL के बराबर नहीं होता। हर कुंजी का अभी एक बार आना स्थायी एक से एक संबंध सिद्ध नहीं करता। अनोखापन की सीमा स्कीमा में देखें; बाद में नई पंक्तियाँ स्थिति बदल सकती हैं।

WITH order_items(item_id, order_id) AS (VALUES (10, 1), (11, 1), (12, 2))
SELECT order_id, COUNT(*) AS item_count
FROM order_items
WHERE order_id IS NOT NULL
GROUP BY order_id
HAVING COUNT(*) > 1;
-- Order 1 has two items in this illustrative dataset.

विदेशी कुंजी, अनोखापन और NULL

विदेशी कुंजी बच्चे के कॉलम को ऐसे संदर्भित मूल कुंजी से जोड़ती है जिसका अनोखापन लागू किया गया हो। इससे बच्चे के मान अनोखे नहीं बनते; कई वस्तुएँ एक ऑर्डर को संदर्भित कर सकती हैं। NULL भी अनुमत हो सकता है, क्योंकि विदेशी कुंजी अकेले भरा हुआ मूल पहचान मान आवश्यक नहीं करती। उदाहरण के स्कीमा में order_id पर अलग से NOT NULL है। ON के वास्तविक कॉलम को घोषित सीमाओं से मिलाएँ, विशेषकर संयुक्त कुंजी या अतिरिक्त शर्तों वाले जोड़ में।

CREATE TABLE orders (
    order_id integer PRIMARY KEY
);
CREATE TABLE order_items (
    item_id integer PRIMARY KEY,
    order_id integer NOT NULL REFERENCES orders(order_id)
);

परिणाम का आवश्यक स्तर चुनें

कई विवरण तालिकाओं को जोड़ने पर एक संग्रह के मान दूसरे संग्रह की प्रत्येक वस्तु के लिए दोहर सकते हैं। इससे योग भ्रामक हो सकता है। हर ऑर्डर की एक पंक्ति चाहिए तो विवरण को पहले उसी स्तर पर समूहित करें। उदाहरण वस्तुओं की संख्या निकालता है और फिर सारांश को ऑर्डर से जोड़ता है। उसका INNER JOIN केवल वस्तुओं वाले ऑर्डर रखता है। बिना वस्तुओं वाले ऑर्डर भी चाहिए तो LEFT JOIN चुनें और स्पष्ट करें कि अनुपस्थित संख्या शून्य दिखानी है या अलग संकेत देना है।

SELECT o.order_id, i.item_count
FROM orders AS o
JOIN (
    SELECT order_id, COUNT(*) AS item_count
    FROM order_items
    GROUP BY order_id
) AS i ON i.order_id = o.order_id;

छोटे डेटा पर तीन जोड़ की तुलना

अंतिम उदाहरण VALUES से छोटे इनपुट बनाता है, इसलिए मूल कुंजियाँ क्वेरी में दिखाई देती हैं। केवल 1 और 3 दोनों तरफ हैं; INNER JOIN दो पंक्तियाँ देता है। पहले का LEFT JOIN कुंजी 2 भी रखता है और तीन पंक्तियाँ देता है। CROSS JOIN सभी नौ जोड़े बनाता है। ये गिनतियाँ लिखे हुए उदाहरण मानों से निकाली गई हैं, प्रदर्शन परीक्षण के परिणाम नहीं हैं। किसी मिलने वाली कुंजी की एक और पंक्ति मन में जोड़ें और देखें कि कौन से नए जोड़े बनने चाहिए।

WITH t1(num) AS (VALUES (1), (2), (3)),
     t2(num) AS (VALUES (1), (3), (5))
SELECT t1.num
FROM t1 INNER JOIN t2 ON t1.num = t2.num
ORDER BY t1.num;
-- Two rows: matching keys 1 and 3.

क्या जाँचें

  • दोनों इनपुट में वास्तविक जोड़ कुंजी की आवृत्ति फ़िल्टर और NULL को ध्यान में रखकर गिनें।
  • PRIMARY KEY, UNIQUE और FOREIGN KEY को वर्तमान डेटा के अवलोकन से अलग जाँचें।
  • गैर-NULL कुंजी की L बाईं और R दाईं आवृत्तियाँ समानता में L × R जोड़े देती हैं।
  • अनुमान के लिए EXPLAIN देखें, लेकिन वृद्धि का कारण कुंजियों से जाँचें; जोड़ का एल्गोरिदम अकेले उसका प्रमाण नहीं है।

उदाहरण समानता वाले जोड़ और PostgreSQL के सिंटैक्स पर आधारित हैं। दूसरी शर्तें, संयुक्त कुंजियाँ, WHERE, समूह और चुने गए कॉलम परिणाम बदल सकते हैं। दी हुई संख्याएँ उदाहरण के VALUES की हैं; क्वेरी चलाकर गति मापने का दावा नहीं किया गया है।

स्रोत

  1. PostgreSQL: table expressions ↗
  2. PostgreSQL: constraints ↗
  3. PostgreSQL: aggregate functions ↗
ऊपर जाएँ ↑