2010-03-15 9 views
5

यह एक एक साधारण समस्या लगती है, लेकिन मैं इसे एक भी का चयन करें या नेस्ट का चयन में काम नहीं कर सकता। पेपर (आलेख) के एक पंक्ति में लेखकों और (यदि कोई हैं) सलाहकार पुनर्प्राप्त करें।mysql 5 (5.1.42) में एकाधिक स्तंभ सबसिलेक्ट

मैं इस समस्या की व्याख्या करने के आदेश, यहाँ दो डेटा तालिकाओं (छद्म)

papers (id, title, c_year) 
persons (id, firstname, lastname) 

के साथ साथ एक लिंक तालिका w/एक अतिरिक्त विशेषता (छद्म) कर रहे हैं:

paper_person_roles(
    paper_id 
    person_id 
    act_role ENUM ('AUTHOR', 'ADVISER') 
) 

यह मूलतः है और कर्मचारियों की एक सूची और/या छात्रों: लिखित कागजात (कागजात तालिका) की एक सूची (टेबल: व्यक्तियों)

एक लेख अपने (1, एन) लेखकों की है।
एक लेख में (0, एन) सलाहकार हो सकते हैं।
कोई व्यक्ति 'लेखक' या 'सलाहकार' भूमिका में हो सकता है (लेकिन एक ही समय में नहीं)।

आवेदन अंत में डालता तालिका निम्नलिखित प्रविष्टियों युक्त पंक्तियों:
चयन/आवेदन में लेख की एक पूरी सूची निकालने, जैसे:

 
TH: || Paper_ID | Author(s)   | Title     | Adviser(s) | 
TD: || 21334 |John Doe, Jeff Tucker|Why the moon looks yellow|Brown, Rayleigh| 
... 

मेरा पहला दृष्टिकोण की तरह था।

SELECT 
    q.id, q.title 
FROM 
    papers AS q 
ORDER BY 
    q.c_year 
और क्वेरी के परिणामों को एक सरणी (एप्लिकेशन में) में सहेजें। इस कदम है, लौटे जानकारी के सरणी पर पाश के बाद और, लेखकों और सलाहकारों (यदि हो तो) को पुनः प्राप्त करने के लिए तैयार बयान के माध्यम से लिंक तालिका तरह से (कागज की आईडी है?):
APPLICATION_LOOP(paper_ids in array) 
    SELECT 
     p.lastname, p.firstname, r.act_role 
    FROM 
     persons AS p, paper_person_roles AS r 
    WHERE 
     p.id=r.person_id AND r.paper_id = ? 
    # The application does further processing from here (pseudo): 
    foreach record from resulting records 
    if record.act_role eq 'AUTHOR' then join to author_column 
    if record.act_role eq 'ADVISER' then join to avdiser_column 
    end 
    print id, author_column, title, adviser_column 
APPLICATION_LOOP 
यह अब तक काम करता है और देता है वांछित आउटपुट। क्या यह को गणना को डीबी में वापस रखने के लिए समझ में आएगी?

मैं नॉनट्रिविअल एसक्यूएल में बहुत कुशल नहीं हूं और एक एकल (संयुक्त या नेस्टेड) ​​चयन कॉल के साथ समाधान नहीं ढूंढ सकता। मैं ने कोशिश की sth।

SELECT 
    q.title 
    (CONCAT_WS(' ', 
    (SELECT p.firstname, p.lastname AS aunames 
     FROM persons AS p, paper_person_roles AS r 
     WHERE q.id=r.paper_id AND r.act_role='AUTHOR') 
    ) 
    ) AS aulist 
FROM 
    papers AS q, persons AS p, paper_person_roles AS r 
कई भिन्नताओं में, लेकिन कोई भाग्य नहीं ...

शायद कुछ मौका है?

अग्रिम धन्यवाद

आरबी।

उत्तर

2

निम्न क्वेरी मेरे परीक्षण डेटा के साथ काम किया, कृपया इसे आज़माएं।

प्रति पेपर लेखकों/सलाहकारों की सूची प्राप्त करने के लिए दो उप-प्रश्न आवश्यक हैं।

Select 
    p.id, 
    p.title, 
    p_aut.aut_name, 
    p_adv.adv_name 
From papers p 
Left Join (
    Select pp_aut.paper_id, 
     Group_Concat(Concat(p_aut.firstname, ' ', p_aut.lastname)) aut_name 
    From paper_person_roles pp_aut 
    Join persons p_aut On (p_aut.id = pp_aut.person_id) 
    Where pp_aut.act_role='AUTHOR' 
    Group By pp_aut.paper_id 
) p_aut On (p_aut.paper_id = p.id) 
Left Join (
    Select pp_adv.paper_id, 
     Group_Concat(Concat(p_adv.firstname, ' ', p_adv.lastname)) adv_name 
    From paper_person_roles pp_adv 
    Join persons p_adv On (p_adv.id = pp_adv.person_id) 
    Where pp_adv.act_role='ADVISER' 
    Group By pp_adv.paper_id 
) p_adv On (p_adv.paper_id = p.id) 
Group By p.id, p.title 
+0

पीटर, आपका उत्तर अविश्वसनीय है। यह वास्तव में * काम करता है, मुझे केवल वांछित आउटपुट (केवल सलाहकारों का अंतिम नाम) प्राप्त करने के लिए सलाहकार से आंतरिक कंकैट (..) को हटाना पड़ा। डेटाबेस बहुत बड़ा नहीं है (अब तक), इसलिए इन एकाधिक जोड़ों में प्रतिक्रिया एक सेकंड के 1/10'th से कम है। यदि कोई सलाहकार वापस नहीं आया है तो कोई रिक्त स्थान डालने का तरीका जानने का प्रयास करेगा (पूर्ण फ़ील्ड लौटाया गया)। बहुत बहुत धन्यवाद! –

+1

आपका स्वागत है :) 'NULL' के बजाय रिक्त स्थान डालने के लिए, आप' COALESCE (p_aut.aut_name, '') ' –

+0

ठीक से उपयोग कर सकते हैं, मैंने आपके उत्तर से बहुत कुछ सीखा। अब मुझे तालिकाओं में पूर्ण सक्षम गुणों को रखने में कुछ विश्वास है (गैर मौजूद पहले- और मध्य नामों के लिए) - क्योंकि केवल तब Concat/Group_Concat फ़ंक्शंस बिना पोस्टप्रोकैसिंग के उपयोगी परिणाम प्रदान करेंगे। बीटीडब्ल्यू। मैंने अस्थायी रूप से उत्पादन वातावरण में क्वेरी का परीक्षण किया और प्रतिक्रिया समय पूर्व "प्रक्रियात्मक" समाधान की तुलना में कम हो गया था। धन्यवाद और शुभ रात्रि –

2

मेरे अनुभवों में, SQL डेटाबेस संगत डेटा की एक पंक्ति में टैब्यूलर डेटा को एकत्रित करने में बहुत अच्छे नहीं हैं। असल में मुझे लगता है कि आप जिस दृष्टिकोण का उपयोग कर रहे हैं वह ठीक है, हालांकि दूसरा विकल्प जो मेरे पास कूदता है, वह व्यक्तियों की तालिका में शामिल होना है, ताकि आपको प्रत्येक व्यक्ति के लिए एक पंक्ति वापस मिल जाएगी जिसमें किसी दिए गए पेपर की भूमिका हो।

कुछ की तरह:

SELECT q.id, q.title, p.firstName, p.lastName, r.act_role FROM papers q, persons p, 
     paper_person_roles r where r.paper_id = q.id and r.person_id = p.id 

कौन सा दिए गए उदाहरण के लिए यदि आप ऊपर से पता चला है निम्नलिखित की तरह आप डेटा प्राप्त होगा:

21334 |Why the moon looks yellow|John Doe |AUTHOR 
21334 |Why the moon looks yellow|Jeff Tucker|AUTHOR 
21334 |Why the moon looks yellow|Brown  |ADVISER 
21334 |Why the moon looks yellow|Rayleigh |ADVISER 

और जो काफी आसान अंत में पार्स करने के लिए है कि आप परिणाम ' फिर से देख रहे हैं

चीजों के इन प्रकार के साथ , यह तालमेल बारे में सब है:
- आप बहुत अधिक समय अधिक से अधिक डेटाबेस के लिए वापस जा खर्च कर रहे हैं?
- क्या वहां बहुत अधिक डेटा है जिसे आप एक साथ में शामिल नहीं कर सकते हैं?
- क्या आपका "अनुकूलन" आपके कोड को पढ़ने में बहुत मुश्किल बना रहा है?

सचमुच, यदि आपका कोड आपके इच्छित तरीके से काम कर रहा है और आपने अभी तक प्रदर्शन स्नैग नहीं मारा है, तो इसे इस तरह से रखें और उस दिन इस निर्णय पर वापस आएं जब आप प्रदर्शन के रूप में प्रदर्शन को देखना शुरू कर देते हैं डेटासेट स्केल अप।

+0

ब्रायन, आपके बोल्डफैक्ड प्रश्न मान्य हैं और मुझे इसके बारे में सोचना होगा। सरल 'सभी तालिकाओं' का चयन करें w/पंक्ति postprocessing (जैसा कि आपने सुझाव दिया है) इस मामले में भी स्वीकार्य होना चाहिए (डीबी में बहुत अधिक पंक्तियां नहीं)। अगर मैं भविष्य में किसी बिंदु पर इसे पूरी तरह से समझने में सक्षम हूं, तो मैं केवल एक चालाक एकाधिक शामिल अनुक्रम (पीटर प्रस्तावित) के रूप में शामिल कर सकता हूं ;-) धन्यवाद –