2012-05-14 17 views
8

के लिए रिटर्निंग मान नहीं डाउनलोड एक डाउनलोड डाउनलोड समय, डाउनलोड-टाइम आईडी और बूनो आईडी शामिल है। दोषों में गलती कोड, डाउनलोड-टाइम आईडी, स्थिति और प्रकार शामिल हैं। एक डाउनलोड में कई दोष हो सकते हैं, और डाउनलोड-टाइम आईडी पर शामिल हो सकते हैं।पोस्टग्रेज़ में बाएं-बाहरी शामिल नल

गलती-कोड के एक सेट को देखते हुए, परिणामों में प्रत्येक गलती-कोड को एक समान गलती के साथ होना चाहिए। यदि डाउनलोड में कोई गलती-कोड नहीं मिला है, तो गलती-कोड शून्य की गलती-गिनती के साथ वापस किया जाना चाहिए।

समस्या को बाहरी जॉइन की आवश्यकता होती है, लेकिन पोस्टग्रेज़ पर अपेक्षित काम के रूप में यह नहीं देखा है क्योंकि यह बाएं तालिका से नल के साथ सेट को वापस नहीं लग रहा है।

क्वेरी, नीचे है कुछ विवरण संक्षिप्तता के लिए बाहर छोड़ दिया साथ:

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
LEFT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id 
    AND f.faultcode IN (1000,1100) 
    AND f.statusid IN(2, 4) 
WHERE (d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') 
    AND d.bunoid = 166501 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

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

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
RIGHT OUTER JOIN fs_fault f ON f.downloadtimeid = d.id 
     AND f.statusid IN(2, 4) 
     AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012' 
     AND d.bunoid = 166501 
WHERE f.faultcode IN (1000,1100) 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

धन्यवाद, आपकी सहायता के लिए सभी! इस साइट को प्यार करो!

+1

क्या आपने अपना डेटा विश्लेषण किया है? मुझे संदेह है कि यह PostgreSQL के भीतर समस्या है ... क्या आप [SQL Fiddle] (http://sqlfiddle.com/) में तालिका संरचना और नमूना डेटा प्रदान कर सकते हैं? – vyegorov

+1

'download_time d बाएं बाहरी जॉइन fs_fault f f.downloadtimeid = d.id' पर बाएं तालिका के रूप में' download_time' है, 'fs_fault' नहीं। जॉइन हालत में कुछ भी नहीं है जिसमें शामिल होने के लिए कौन सी टेबल छोड़ी गई है या सही है। – JayC

उत्तर

20

मैं अपना उत्तर दे रहा हूं क्योंकि मुझे अन्य उत्तरों के बारे में महत्वपूर्ण संदेह हैं। आपको फिल्टर आवश्यकताओं के बारे में सावधान रहना होगा। याद रखें, में शामिल होने के बाद जहां क्लॉज चलाता है। इसलिए यदि कोई फ़िल्टर आवश्यकता है जहां खंड है जो गैर-बाहरी शामिल तालिका का संदर्भ देता है, तो आपके पास (बाहरी परिस्थितियों में) आपके बाहरी जुड़ने को रद्द कर दिया गया है। तो अपना एसक्यूएल लेना, ऐसा लगता है कि सबसे आसान समाधान या तो उचित रूप से शामिल होने या तालिका के नामों को उचित रूप से स्थानांतरित करने के लिए है, और उसके बाद फ़िल्टर स्थितियों को क्लॉज और शामिल खंड में से बाहर ले जाएं।

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id 
    AND f.faultcode IN (1000,1100) 
    AND f.statusid IN(2, 4) 
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') 
    AND d.bunoid = 166501 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

एक और तरीका है जो मेरा मानना ​​है कि बराबर होना चाहिए

SELECT f.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM download_time d 
RIGHT OUTER JOIN fs_fault f ON 
    f.downloadtimeid = d.id 
    AND d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') 
    AND d.bunoid = 166501 
WHERE 
    f.faultcode IN (1000,1100) 
    AND f.statusid IN(2, 4) 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

है यह नहीं सख्ती से चाहे कहीं fs_fault पर फिल्टर आवश्यकताएँ हैं करता है के रूप में। (और आपका एसक्यूएल इंजन वैसे भी सभी को बदलने जा रहा है)।

संपादित करें: यहां एक SQLFiddle है जो क्लॉज बनाम खंड में फ़िल्टरिंग का प्रदर्शन करता है।

+1

आप 'जॉइन' शर्तों बनाम 'WHERE' खंड के बारे में सही हैं। मैंने उस संबंध में अपना जवाब तय कर दिया। मुझे नहीं लगता कि आपने वांछित फॉल्टकोड को दिखाने के तरीके के बारे में अपने प्रश्न को संबोधित किया है, भले ही कोई भी * नहीं हो। – kgrittn

+0

सभी का धन्यवाद: मैंने सभी उत्तरदाताओं को वोट दिया, क्योंकि मैंने प्रत्येक से कुछ सीखा। हालांकि, जेसी, तुम्हारा सबसे करीबी था। एकमात्र परिवर्तन 'f.faultcode IN (1000,1100)' को उस खंड में स्थानांतरित करना था। ऐसा करने पर, सही गलती-कोड प्रदर्शित होते हैं। धन्यवाद, जयसी! – MAbraham1

+0

मुझे काम करने के लिए SQLFiddle नहीं मिल सका। मैं आईई 7.0.5730.13CO का उपयोग कर रहा हूं, क्योंकि मैं काम पर हूं। मुझे इसे घर पर आजमाने की ज़रूरत है जहां मैं आमतौर पर क्रोम चलाता हूं। – MAbraham1

2

इसके लिए RIGHT OUTER JOIN की आवश्यकता होगी। सही बाहरी सम्मिलन में NULL एस के साथ दाएं तालिका से सभी मान शामिल हैं, जहां बाएं तालिका में कोई प्रविष्टि नहीं है (मुझे यकीन नहीं है कि यह GROUP BY के साथ काम करेगा, हालांकि ... यदिfs_fault एक तालिका थी सभी गलती कोड।

आपके मामले में, fs_fault में डाउनलोड के लिए सभी दोष शामिल हैं। क्या यह अप्रत्याशित व्यवहार का मामला हो सकता है?

1

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

लेकिन, इसमें आपके सभी गलती कोड शामिल नहीं हैं। क्या हो रहा है कि मानदंडों को पूरा करने वाले एक या अधिक कोडों के लिए आपके पास कोई दोष नहीं है।

इस काम के लिए आपको एक टेबल की आवश्यकता है जिसमें सभी गलती कोड शामिल हैं। यहां मैं पहली तालिका के रूप में गलती कोड की एक सूची बना देता हूं। मुझे लगता है कि निम्न क्वेरी करता है:

SELECT thefaults.faultcode, f.downloadtimeid, d.downloadtime, count(*) as faultcount 
FROM (select 1000 as faultcode union all select 1100 
    ) thefaults join 
     fs_fault f 
     on f.faultcode = thefaults.faultcode and 
     f.statusid in (2, 4) left outer join 
     download_time d 
     ON f.downloadtimeid = d.id 
WHERE (d.downloadtime BETWEEN '04/11/2011' AND '05/01/2012') AND 
     d.bunoid = 166501 
GROUP BY d.bunoid, f.downloadtimeid, d.downloadtime, f.faultcode 

मैं मानता हूं: मैं एसक्यूएल सर्वर सिंटैक्स का उपयोग कर रहा हूँ "thefaults" बनाने के लिए।

+0

यदि किसी गलती के पास कोई डाउनलोड समय नहीं है, तो उसे क्लॉज द्वारा फ़िल्टर किया जाएगा। – JayC

+0

एक मानता है कि प्रश्नकर्ता चाहता है। –

2

आप faultcode से मायने रखता है चाहते हैं, यह सबसे सरल समाधान की तरह लगता है:

WITH fc(faultcode) AS (VALUES (1000,1100)) 
SELECT fc.faultcode, count(d.downloadtimeid) as faultcount 
    FROM fc 
    LEFT JOIN (fs_fault f ON f.faultcode = fc.faultcode 
         AND f.statusid IN(2, 4) 
    JOIN download_time d ON d.id = f.downloadtimeid 
         AND d.bunoid = 166501 
         AND d.downloadtime::date BETWEEN date '2011-04-11' 
                AND date '2011-05-01') 
    GROUP BY fc.faultcode 
    ORDER BY fc.faultcode 

ध्यान दें कि मैं अपनी शर्तों, यदि वे सही statusid या bunoid की जरूरत नहीं है, जहां दोष नहीं गिने जाते हैं रखा। मुझे थोड़ा डर था कि तिथि चयन शायद आपने जो सोचा था वह नहीं कर रहा था, इसलिए मैंने एक विकल्प सुझाया। यहां तक ​​कि अगर आप TIMESTAMP WITHOUT TIME ZONE का उपयोग कर रहे हैं तो वह भी नहीं कर सकता है, लेकिन यह एक और कहानी है। मैंने ORDER BY क्लॉज भी जोड़ा, क्योंकि आप शायद परिणाम को असंगत क्रम में नहीं चाहते हैं; उस खंड के बिना यह GROUP BY अनुक्रम में हो सकता है या नहीं हो सकता है, और यह चेतावनी के बिना बदल सकता है।

+0

यदि किसी गलती के पास कोई डाउनलोड समय नहीं है, तो उसे क्लॉज द्वारा फ़िल्टर किया जाएगा। – JayC

+0

ओह। जुड़ने के मूल्यांकन के आदेश को मजबूर करने के लिए कोष्ठक जोड़कर फिक्स्ड। धन्यवाद! – kgrittn

+0

@ जेएसी ने अपने जवाब में 'जॉइन' की बनाम 'WHERE' खंड के बारे में एक अच्छा बिंदु बनाया। जैसा कि लिखा गया था, यदि किसी विशेष गलती के लिए * केवल * पंक्तियों को शर्तों से बाहर रखा गया था, तो फॉल्टोकडे दिखाई नहीं देगा। शर्तों को स्थानांतरित करके फिक्स्ड। – kgrittn

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