2012-09-02 12 views
14

मैं postgresql के साथ एक क्वेरी बनाने की कोशिश कर रहा हूं। डेटाबेस में दो संबंध हैं: "साम्राज्य", जिसमें कुछ अंग्रेजी राजा शामिल हैं, और "राजवंश", जिसमें स्टुअर्ट राजवंशएसक्यूएल: सबक्वायरी में बहुत से कॉलम हैं

संबंध "साम्राज्य" में राजा का नाम शामिल है और जब उसका राज्य शुरू हुआ और समाप्त हो गया । संबंध "वंश" में नाम, लिंग, जन्म और मृत्यु शामिल है।

जो मैं पूछताछ करने की कोशिश कर रहा हूं वह वह राजा है जो मरने पर सबसे पुराना था।

मेरी क्वेरी के साथ मैं लाइन 3 (नहीं) पर यह संदेश मिल रहा हूँ:

SELECT kingdom.king, dinasty.birth, dinasty.death 
FROM kingdom, dinasty 
WHERE kingdom.king = dinasty.name AND kingdom.king NOT IN 
(
    SELECT DISTINCT R1.king, R1.birth, R1.death 
    FROM 
    (
     SELECT DISTINCT R1.king, D1.birth, D1.death 
     FROM kingdom AS R1, dinasty AS D1, dinasty AS D2 
     WHERE R1.king=D1.name 
    ) AS R1, 
    (
     SELECT DISTINCT R1.king, D1.birth, D1.death 
     FROM kingdom AS R1, dinasty AS D1, dinasty AS D2 
     WHERE R1.king=D1.name 
    ) AS R2 
    WHERE R1.death-R1.birth < R2.death-R2.birth 
); 

क्या है अंदर नहीं सही है: subquery has too many columns

इस क्वेरी है।

+1

यह आपके कोड को प्रभावित नहीं करता है, लेकिन कृपया वंश को सही ढंग से वर्तनी दें। –

उत्तर

18

आप अपने सबक्वेरी में तीन कॉलम पेश कर रहे हैं, लेकिन IN खंड में एक भी एक उनमें से की तुलना। सबक्वेरी में IN के लिए सिर्फ आवश्यक स्तंभ (r1.king) का चयन करें:

SELECT kingdom.king, dinasty.birth, dinasty.death 
FROM kingdom, dinasty 
WHERE kingdom.king = dinasty.name AND kingdom.king NOT IN 
(
    SELECT DISTINCT R1.king 
    FROM 
    (
     SELECT DISTINCT R1.king, D1.birth, D1.death 
     FROM kingdom AS R1, dinasty AS D1, dinasty AS D2 
     WHERE R1.king=D1.name 
    ) AS R1, 
    (
     SELECT DISTINCT R1.king, D1.birth, D1.death 
     FROM kingdom AS R1, dinasty AS D1, dinasty AS D2 
     WHERE R1.king=D1.name 
    ) AS R2 
    WHERE R1.death-R1.birth < R2.death-R2.birth 
); 
+0

बहुत बहुत धन्यवाद :) – Epi

+0

इसके अलावा, यदि आप ऐसा कर सकते हैं, तो उपखंड को खंड से (एक उपयुक्त फ़ील्ड के साथ एक व्युत्पन्न तालिका के रूप में) में स्थानांतरित करने का प्रयास करें, क्योंकि यह काफी तेज़ होगा, केवल एक बार मूल्यांकन करेगा प्रति पंक्ति एक बार। – d11wtq

8

के रूप में जवाब दिया गया था, अपने स्तंभ संख्या से मेल नहीं खाती है, लेकिन वहाँ एक बहुत सरल तरीका यह लिखने के लिए है।

प्रश्न लिखते समय, चरणों में उन्हें सोचना सबसे अच्छा है। सबसे पहले, आप को पता है कितनी पुरानी प्रत्येक राजा था, जब वे मर गया की जरूरत है:

SELECT *, death-birth AS lived_for FROM dinasty 

अब आप है कि, आप प्रत्येक राज्य

SELECT DISTINCT ON(name) name, birth, death, lived_for 
    FROM (
     SELECT *, death-birth AS lived_for FROM dinasty 
    ) a 
    ORDER BY name, lived_for DESC 
; 

के लिए सबसे लंबे समय तक रहते थे राजा को खोजने के लिए DISTINCT पर उपयोग कर सकते हैं अलग-अलग मूल्य प्रत्येक विशिष्ट मान के लिए पहली पंक्ति लेंगे, इसलिए यह महत्वपूर्ण है कि आप इसे सही ORDER BY से जोड़ दें। सबसे पहले हम वंश के नाम से आदेश देते हैं, फिर राजा के लिए अवरोही क्रम में कितने समय तक रहता था। इसका मतलब है कि प्रत्येक वंश के लिए दिखाया गया पहला राजा सबसे लंबे समय तक जीवित रहेगा, और वह रिकॉर्ड है कि प्रत्येक राजवंश के लिए डिस्टिंट चालू रहेगा।

ध्यान दें कि मैं भी हटा दिया kindgom को शामिल हों, लेकिन आप अगर जरूरत में कि वापस जोड़ सकते हैं: अंत में

SELECT k.*, oldest.* 
    FROM (
    SELECT DISTINCT ON(name) name, birth, death, lived_for 
     FROM (
      SELECT *, death-birth AS lived_for FROM dinasty 
     ) a 
     ORDER BY name, lived_for DESC 
    ) oldest 
    JOIN kingdom k ON k.king = oldest.name 
; 

, यदि आप कभी-चयन उप एक में एकाधिक स्तंभों उपयोग करने की आवश्यकता है, तो आप उपयोग कर सकते हैं ROW() निर्माण:

SELECT ... 
    FROM table_a 
    WHERE ROW(f1, f2, f3) NOT IN (SELECT f1a, f2a, f3a FROM ...) 
; 
+0

यह क्यों कम किया गया था? –

+0

अच्छा सवाल; मेरे लिए कुछ भी गलत नहीं है - स्पष्टीकरण में एक टिप्पणी छोड़ना विनम्र होगा। –

+0

ROW विकल्प को इंगित करने के लिए धन्यवाद! मेरा हल (थोड़ा अलग) मुद्दा :) – wmebane

संबंधित मुद्दे