2011-01-14 13 views
19

मुझे चालान की एक तालिका और कुंजी से संबंधित संबंधित डेटा की एक बाल तालिका मिली है। विशेष रूप से, प्रत्येक चालान के लिए, मुझे केवल बाल तालिका से पहली संबंधित पंक्ति में रूचि है। यह देखते हुए कि मैं प्रत्येक चालान कुंजी के लिए एक संबंधित पंक्ति चाहता हूं - मैं इसे कैसे पूरा करूं?मैं सबक्वायरी की पहली पंक्ति में कैसे शामिल हो सकता हूं?

Select i.[Invoice Number], 
     c.[Carrier Name] 
From Invoice i 
    Left Join Carriers c on i.[InvoiceKey] = c.[InvoiceKey] 
Where -- what? 

मैं शब्दार्थ बोल लगता है, क्या मैं Top 1 c.CarrierName Group by InvoiceKey की अवधारणा के समान कुछ के लिए देख रहा हूँ (या क्या है कि की अवधारणा हो सकता है अगर है कि T-SQL में संभव थी।)

मैं मैंने एक सबक्वायरी पर बाएं जुड़ने के बारे में सोचा है, लेकिन यह बहुत ही कुशल प्रतीत नहीं होता है। क्या किसी को यह कुशलता से प्राप्त करने के लिए कोई टी-एसक्यूएल चाल है?

संपादित क्षमा करें दोस्तों, मैं, इस एसक्यूएल सर्वर 2000 है, इसलिए जब तक मैं वर्तमान एसक्यूएल सर्वर के लिए 2005/2008 प्रतिक्रियाओं upvotes देने के लिए जा रहा हूँ कि काम करेंगे उल्लेख करना भूल गया मैं उन्हें मैं स्वीकार नहीं कर सकते मैं डरता हूँ

+0

दूसरी तालिका किसी भी विशेषता है कि कहते हैं जो पंक्ति है प्रथम, द्वितीय आदि – Chandu

+0

@Cybernate नहीं है, सूचकांक के अनुक्रम के अलावा अन्य है – BenAlabaster

उत्तर

24

परंतु Carriers है कि एक PRIMARY KEYid कहा जाता है:

SELECT i.[Invoice Number], 
     c.[Carrier Name] 
FROM Invoice i 
JOIN Carriers c 
ON  c.id = 
     (
     SELECT TOP 1 ID 
     FROM Carriers ci 
     WHERE ci.InvoiceKey = i.InvoiceKey 
     ORDER BY 
       id -- or whatever 
     ) 
+0

यह वाकई बहुत अच्छा है! – abatishchev

+0

इस समूह का प्रदर्शन समूह के मुकाबले खराब होने की संभावना है। आप चालान में प्रत्येक पंक्ति के लिए वाहक तालिका के खिलाफ एक सहसंबंधित सबक्वायरी निष्पादित कर रहे हैं। –

+4

@ क्रिस: क्या तुलना में? आपने एक कामकाजी उदाहरण नहीं दिया है। – Quassnoi

1

यह मेरे लिए काम करता है:

select ir.[Invoice Number], c.[Carrier Name] 
from 
    (select ROW_NUMBER() over (order by i.[Invoice Number] asc) AS RowNumber, i.[Invoice Number], i.InvoiceKey 
    from Invoice i) AS ir 
left join Carriers c 
on ir.InvoiceKey = c.InvoiceKey 
where RowNumber = 1 
union all 
select ir.[Invoice Number], NULL as [Carrier Name] 
from 
    (select ROW_NUMBER() over (order by i.[Invoice Number] asc) AS RowNumber, i.[Invoice Number] 
    from Invoice i) AS ir 
where RowNumber > 1 

या

select TOP 1 i.[Invoice Number], c.[Carrier Name] 
from Invoice i 
left join Carriers c 
on i.InvoiceKey = c.InvoiceKey 
union all 
select ir.[Invoice Number], NULL as [Carrier Name] 
from 
    (select ROW_NUMBER() over (order by i.[Invoice Number] asc) AS RowNumber, i.[Invoice Number] 
    from Invoice i) AS ir 
where RowNumber > 1 
+0

+1 करना चाहेंगे नौकरी अगर मैं SQL सर्वर 2005+ पर था, लेकिन मैं उल्लेख करना भूल गया कि मुझे SQL Server 2000 बॉक्स पर इस रन की आवश्यकता है। – BenAlabaster

0
group by carriername having max(invoicenumber) 

प्रत्येक चालान के लिए पहली वाहक पाने के लिए:

group by invoicenumber having max(carriername) 
-- substitute the column you want to order by for carrier name to change which is 'first' 
+0

यह काम नहीं करेगा - यह केवल मुझे उच्चतम चालान संख्या वाले वाहक का वाहक नाम देगा। मुझे प्रत्येक चालान के लिए पहला वाहक चाहिए। – BenAlabaster

+0

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

+0

याद रखें- क्लॉज द्वारा समूह के बाद क्लॉज लागू किए जाते हैं :-) –

1
;with cteRowNumber as (
    select c.InvoiceKey, c.[Carrier Name], ROW_NUMBER() over (partition by c.InvoiceKey order by c.[Carrier Name]) as RowNum 
     from Carriers c 
) 
select i.[Invoice Number], 
     rn.[Carrier Name] 
    from Invoice i 
     left join cteRowNumber rn 
      on i.InvoiceKey = rn.InvoiceKey 
       and rn.RowNum = 1 
+0

काम नहीं करता है। सभी रिकॉर्ड्स में शामिल हों, न केवल पहले – abatishchev

+0

@abatishchev: मुझे यह नहीं दिखाई देता है। अगर मैं अपनी जॉइन स्थिति के हिस्से के रूप में 'rn.RowNum = 1' समेत हूं, तो केवल" पहले "(विंडो विंडो फ़ंक्शन के ऑर्डरिंग द्वारा परिभाषित) में शामिल होना चाहिए। –

+0

+1 तकनीकी रूप से सही है, लेकिन मैं यह उल्लेख करना भूल गया कि मैं SQL Server 2000 की तलाश में था, इसलिए सीटीई एक विकल्प नहीं है। – BenAlabaster

1

यह मैं इसे कैसे करना होगा, तुम्हारा (MySQL शैली) की तुलना में एक अलग सिंटैक्स का उपयोग है, लेकिन मुझे लगता है कि आप अपने समाधान के लिए यह लागू हो सकते हैं:

SELECT i.invoiceNumber, c.carrierName 
FROM Invoice as i 
LEFT JOIN Carriers as c ON (c.id = (SELECT id FROM Carriers WHERE invoiceKey = i.invoiceKey ORDER BY id LIMIT 1)) 

इस चालान से सभी रिकॉर्ड ले जाएगा, और वाहकों से एक (या शून्य) रिकॉर्ड में शामिल हों, विशेष रूप से रिकॉर्ड जिसमें एक ही चालान है और केवल पहला।

जब तक आपके पास career.invoice पर कोई अनुक्रमणिका है, तो इस क्वेरी का प्रदर्शन स्वीकार्य होना चाहिए।

सेबस्टियन

1

ऐसे मामलों में मैं अक्सर एक उपकरण है जो मैं यहाँ अपने उदाहरण के लिए लागू रोजगार और नीचे वर्णन:

SELECT 
    i.[Invoice Number], 
    c.[Carrier Name] 
FROM Invoice i 
    INNER JOIN Carriers c ON i.InvoiceKey = c.InvoiceKey 
    INNER JOIN (
    SELECT MIN(ID) AS ID 
    FROM Carriers 
    GROUP BY InvoiceKey 
) c_top ON c.ID = c_top.ID 

मुझे लगता है, यह मोटे तौर पर क्वास्नोई ने पोस्ट किया है, केवल मैं इस तरह से SELECT TOP का उपयोग करने से बचने की कोशिश करता हूं।

InvoiceCarriers के साथ उनके लिंकिंग अभिव्यक्ति (InvoiceKey इस मामले में) के आधार पर जुड़ गया है। अब, Carriers में InvoiceKey के लिए कई पंक्तियां हो सकती हैं, इसलिए हमें आउटपुट को सीमित करने की आवश्यकता है। और यह एक व्युत्पन्न तालिका का उपयोग कर किया जाता है।

व्युत्पन्न तालिका समूह कैरियर से उसी अभिव्यक्ति के आधार पर पंक्तियां चलाता है जिसका उपयोग दो तालिकाओं (InvoiceKey) को जोड़ने के लिए किया जाता है।

और एक और तरीका है: व्युत्पन्न तालिका में शामिल होने के बजाय आप IN (subquery) का उपयोग उसी प्रभाव से कर सकते हैं। यही कारण है, पूरा क्वेरी तो इस प्रकार दिखाई देगा:

SELECT 
    i.[Invoice Number], 
    c.[Carrier Name] 
FROM Invoice i 
    INNER JOIN Carriers c ON i.InvoiceKey = c.InvoiceKey 
    AND c.ID IN (SELECT MIN(ID) FROM Carriers GROUP BY InvoiceKey) 
संबंधित मुद्दे