आप वास्तव में यह सब एक सीटीई चयन क्वेरी में कर सकते हैं, बिना किसी फ़ंक्शन का उपयोग किए। यहां बताया गया है:
सबसे पहले, इस पैरेंट/चाइल्ड टेबल स्ट्रक्चर पर विचार करें:
CREATE TABLE P (ID INT PRIMARY KEY, Description VARCHAR(20));
CREATE TABLE C (ID INT PRIMARY KEY, PID INT,
Description VARCHAR(20),
CONSTRAINT fk FOREIGN KEY (PID) REFERENCES P(ID));
(मैंने टाइपिंग को बचाने के लिए P और C का उपयोग किया है!)
और कुछ परीक्षण डेटा जोड़ने देता है, जो प्रश्न पूछने वाले से मेल खाता है:
INSERT INTO P VALUES (36, 'Blah Blah');
INSERT INTO P VALUES (20, 'Pah Pah');
INSERT INTO C VALUES (1, 36, 'Bob');
INSERT INTO C VALUES (2, 36, 'Gary');
INSERT INTO C VALUES (3, 36, 'Reginald');
INSERT INTO C VALUES (4, 20, 'Emily');
INSERT INTO C VALUES (5, 20, 'Dave');
फिर अंत में, सीटीई एक्सप्रेशन:
WITH
FirstItems (PID, FirstCID) AS (
SELECT C.PID, MIN(C.ID)
FROM C
GROUP BY C.PID
),
SubItemList (PID, CID, ItemNum) AS (
SELECT C.PID, C.ID, 1
FROM C JOIN FirstItems FI ON (C.ID = FI.FirstCID)
UNION ALL
SELECT C.PID, C.ID, IL.ItemNum + 1
FROM C JOIN SubItemList IL ON C.PID = IL.PID AND C.ID > CID
),
ItemList (PID, CID, ItemNum) AS (
SELECT PID, CID, MAX(ItemNum)
FROM SubItemList
GROUP BY PID, CID
),
SubArrayList (PID, CID, Array, ItemNum) AS (
SELECT IL.PID, IL.CID, CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum
FROM ItemList IL JOIN C ON IL.CID = C.ID
WHERE IL.ItemNum = 1
UNION ALL
SELECT IL.PID, IL.CID, AL.Array + ',' + CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum
FROM ItemList IL
JOIN SubArrayList AL ON (IL.PID = AL.PID AND IL.ItemNum = AL.ItemNum + 1)
JOIN C ON (IL.CID = C.ID)
),
MaxItems (PID, MaxItem) AS (
SELECT PID, MAX(ItemNum)
FROM SubItemList
GROUP BY PID
),
ArrayList (PID, List) AS (
SELECT SAL.PID, SAL.Array
FROM SubArrayList SAL
JOIN MaxItems MI ON (SAL.PID = MI.PID AND SAL.ItemNum = MI.MaxItem)
)
SELECT P.ID, P.Description, AL.List
FROM ArrayList AL JOIN P ON P.ID = AL.PID
ORDER BY P.ID
परिणाम:
ID Description List
-- -------------- --------
20 Pah Pah Emily,Dave
36 Blah Blah Bob,Gary,Reginald
यहाँ क्या हो रहा है, यह समझाने के लिए, मैं CTE के प्रत्येक भाग और यह क्या करता है, इसका वर्णन करूँगा।
पहले आइटम सभी बच्चों को देखता है, और अगले पुनरावर्ती चयन के लिए एंकर के रूप में उपयोग करने के लिए प्रत्येक अभिभावक समूह में सबसे कम आईडी ढूंढता है:
FirstItems (PID, FirstCID) AS (
SELECT C.PID, MIN(C.ID)
FROM C
GROUP BY C.PID
)
उपआइटम सूची एक पुनरावर्ती चयन है जो पिछली क्वेरी से सबसे कम बच्चे को उठाता है, और 1 से शुरू होने वाले प्रत्येक बच्चे को एक वृद्धिशील आइटम नंबर आवंटित करता है:
SubItemList (PID, CID, ItemNum) AS (
SELECT C.PID, C.ID, 1
FROM C JOIN FirstItems FI ON (C.ID = FI.FirstCID)
UNION ALL
SELECT C.PID, C.ID, IL.ItemNum + 1
FROM C JOIN SubItemList IL ON C.PID = IL.PID AND C.ID > CID
)
समस्या यह है कि यह बहुत सारी वस्तुओं को डुप्लिकेट और दोहराता है, इसलिए आइटमसूची प्रत्येक समूह से केवल अधिकतम चुनने के लिए इसे फ़िल्टर करें:
ItemList (PID, CID, ItemNum) AS (
SELECT PID, CID, MAX(ItemNum)
FROM SubItemList
GROUP BY PID, CID
)
अब हमारे पास माता-पिता की एक आईडी सूची है जिसमें प्रत्येक बच्चे की संख्या 1 से x तक है:
PID CID ItemNum
----------- ----------- -----------
36 1 1
36 2 2
36 3 3
20 4 1
20 5 2
SubArrayList बच्चों की पंक्तियों को लेता है, संख्याओं की सूची में बार-बार जुड़ता है और एक ही विवरण से शुरू करते हुए सभी विवरणों को एक-दूसरे से जोड़ना शुरू करता है:
SubArrayList (PID, CID, Array, ItemNum) AS (
SELECT IL.PID, IL.CID, CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum
FROM ItemList IL JOIN C ON IL.CID = C.ID
WHERE IL.ItemNum = 1
UNION ALL
SELECT IL.PID, IL.CID, AL.Array + ',' + CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum
FROM ItemList IL
JOIN SubArrayList AL ON (IL.PID = AL.PID AND IL.ItemNum = AL.ItemNum + 1)
JOIN C ON (IL.CID = C.ID)
)
परिणाम अब है:
PID CID Array ItemNum
----------- ----------- ----------------- -----------
36 1 Bob 1
20 4 Emily 1
20 5 Emily,Dave 2
36 2 Bob,Gary 2
36 3 Bob,Gary,Reginald 3
तो हमें बस इतना करना है कि सभी आंशिक रूप से संयोजित पंक्तियों से छुटकारा पाएं।
अधिकतम आइटम बस माता-पिता और उनके उच्चतम आइटम नंबरों की एक सूची पकड़ लेता है, जो निम्न क्वेरी को थोड़ा आसान बनाता है:
MaxItems (PID, MaxItem) AS (
SELECT PID, MAX(ItemNum)
FROM SubItemList
GROUP BY PID
)
ArrayList पिछली क्वेरी से प्राप्त अधिकतम आइटम संख्या का उपयोग करके आंशिक रूप से संयोजित पंक्तियों का अंतिम चयन करता है:
ArrayList (PID, List) AS (
SELECT SAL.PID, SAL.Array
FROM SubArrayList SAL
JOIN MaxItems MI ON (SAL.PID = MI.PID AND SAL.ItemNum = MI.MaxItem)
)
और अंत में, जो कुछ बचा है, वह परिणाम को क्वेरी करना है:
SELECT P.ID, P.Description, AL.List
FROM ArrayList AL JOIN P ON P.ID = AL.PID
ORDER BY P.ID