बाएं हाथ से शीर्ष 1


94

नीचे दिए गए क्वेरी को देखते हुए एक ही मार्कर कुंजी के साथ dps_markers में कई पंक्तियाँ हो सकती हैं, लेकिन हम केवल पहले के खिलाफ शामिल होना चाहते हैं। अगर मैं यह क्वेरी लेता हूं और शीर्ष 1 और ORDER को हटा देता हूं, तो मुझे mbg.marker_value के लिए एक मूल्य मिलता है, लेकिन इसे वैसे ही चलाएं जब यह हमेशा शून्य हो

SELECT u.id, mbg.marker_value 
FROM dps_user u
LEFT JOIN 
    (SELECT TOP 1 m.marker_value, um.profile_id
     FROM dps_usr_markers um (NOLOCK)
         INNER JOIN dps_markers m (NOLOCK) 
             ON m.marker_id= um.marker_id AND 
                m.marker_key = 'moneyBackGuaranteeLength'
     ORDER BY m.creation_date
    ) MBG ON MBG.profile_id=u.id 
WHERE u.id = 'u162231993'

जवाबों:


202

बाईं ओर के बजाय OUTER APPLY का उपयोग करें:

SELECT u.id, mbg.marker_value 
FROM dps_user u
OUTER APPLY 
    (SELECT TOP 1 m.marker_value, um.profile_id
     FROM dps_usr_markers um (NOLOCK)
         INNER JOIN dps_markers m (NOLOCK) 
             ON m.marker_id= um.marker_id AND 
                m.marker_key = 'moneyBackGuaranteeLength'
     WHERE um.profile_id=u.id 
     ORDER BY m.creation_date
    ) AS MBG
WHERE u.id = 'u162231993';

JOIN के विपरीत, APPLY आपको आंतरिक क्वेरी के अंदर u.id का संदर्भ देने की अनुमति देता है।


धन्यवाद @ रेमस, इसने मेरी मदद की।
सार्थक शाह

3

इस तरह की स्थितियों को डीबग करने की कुंजी यह है कि उत्पादन क्या है यह देखने के लिए अपने दम पर सबक्वीरी / इनलाइन व्यू चलाएं:

  SELECT TOP 1 
         dm.marker_value, 
         dum.profile_id
    FROM DPS_USR_MARKERS dum (NOLOCK)
    JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id 
                                AND dm.marker_key = 'moneyBackGuaranteeLength'
ORDER BY dm.creation_date

यह देखते हुए कि आप देखेंगे कि profile_idमान उस u.idमूल्य से मेल नहीं खाता u162231993, जो यह बताता है कि कोई mbgसंदर्भ क्यों लौटेगा null(बाईं ओर का धन्यवाद, अगर आपको यह आंतरिक जुड़ाव मिला तो आपको कुछ भी नहीं मिलेगा)।

आपने अपने आप को एक कोने में उपयोग करके कोडित कर लिया है TOP, क्योंकि अब यदि आप इसे अन्य उपयोगकर्ताओं के लिए चलाना चाहते हैं, तो आपको क्वेरी को ट्विक करना होगा। एक बेहतर तरीका होगा:

   SELECT u.id, 
          x.marker_value 
     FROM DPS_USER u
LEFT JOIN (SELECT dum.profile_id,
                  dm.marker_value,
                  dm.creation_date
             FROM DPS_USR_MARKERS dum (NOLOCK)
             JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id 
                                         AND dm.marker_key = 'moneyBackGuaranteeLength'
           ) x ON x.profile_id = u.id
     JOIN (SELECT dum.profile_id,
                  MAX(dm.creation_date) 'max_create_date'
             FROM DPS_USR_MARKERS dum (NOLOCK)
             JOIN DPS_MARKERS dm (NOLOCK) ON dm.marker_id= dum.marker_id 
                                         AND dm.marker_key = 'moneyBackGuaranteeLength'
         GROUP BY dum.profile_id) y ON y.profile_id = x.profile_id
                                   AND y.max_create_date = x.creation_date
    WHERE u.id = 'u162231993'

इसके साथ, आप सिस्टम में किसी भी उपयोगकर्ता के रिकॉर्ड को चेक करने के idलिए whereक्लॉज में मान बदल सकते हैं ।


2

क्योंकि TOP 1ऑर्डर किए गए सब-क्वेरी में से profile_id = 'u162231993' निकालें where u.id = 'u162231993'और फिर परिणाम नहीं देखें।

जो चल रहा है उसे समझने के लिए उप-क्वेरी को अलग से चलाएँ।


ठीक है, मुझे लगता है कि मैं देख रहा हूं कि अब आपका क्या मतलब है। अभी भी यह काम करने के लिए सक्षम होने की जरूरत है। मूल रूप से मैं तालिका dps_markers तालिका में एक से अधिक पंक्ति हो सकती हैं, जो बाहरी क्वेरी में कारण बनता है जिसे हमें रोकने की आवश्यकता होती है।
dstarh

1

दामिर सही है,

आपकी उपशम को यह सुनिश्चित करने की आवश्यकता है कि dps_user.id um.profile_id के बराबर है, अन्यथा यह शीर्ष पंक्ति को पकड़ लेगा, जो शायद 'u162231993' की आपकी आईडी के बराबर नहीं है।

आपकी क्वेरी इस तरह दिखनी चाहिए:

SELECT u.id, mbg.marker_value 
FROM dps_user u
LEFT JOIN 
    (SELECT TOP 1 m.marker_value, um.profile_id
     FROM dps_usr_markers um (NOLOCK)
         INNER JOIN dps_markers m (NOLOCK) 
             ON m.marker_id= um.marker_id AND 
                m.marker_key = 'moneyBackGuaranteeLength'
     WHERE u.id = um.profile_id
     ORDER BY m.creation_date
    ) MBG ON MBG.profile_id=u.id 
WHERE u.id = 'u162231993'

1
हां, मैंने अभी कोशिश की है, लेकिन उप-चयन में दृश्यमान नहीं है। बहु-भाग पहचानकर्ता "u.id" बाध्य नहीं किया जा सकता है।
dstarh

1
आप WHERE um.profile_id = 'u162231993'उप-क्वेरी और WHERE mbg.marker_value IS NOT NULLबाहर पर डाल सकते हैं ।
दामिर सुदारेविक

1
मैं profile_id को नहीं करूंगा, यह किसी अन्य जॉइन से होगा। यह बहुत बड़ी क्वेरी से बाहर खींच लिया गया था
dstarh

1
ठीक है, चर का उपयोग करें @SearchFor = 'u162231993'और फिर उस WHEREडेटा का उपयोग करें या कुछ डेटा और तालिका संरचनाएं पोस्ट करें ताकि अन्य लोग इसमें मदद कर सकें और इसे आज़मा सकें।
दामिर सुद्रेविक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.