लेफ्ट जॉइन विथ व्हेयर क्लॉज


162

मुझे सेटिंग्स तालिका से सभी डिफ़ॉल्ट सेटिंग्स को पुनः प्राप्त करने की आवश्यकता है, लेकिन x वर्ण के लिए मौजूद होने पर वर्ण सेटिंग को भी पकड़ो।

लेकिन यह क्वेरी केवल उन सेटिंग्स को पुनर्प्राप्त कर रही है जहां चरित्र = 1 है, डिफ़ॉल्ट सेटिंग्स नहीं अगर उपयोगकर्ता किसी को भी निपटाता है।

SELECT `settings`.*, `character_settings`.`value`
FROM (`settings`)
LEFT JOIN `character_settings` 
ON `character_settings`.`setting_id` = `settings`.`id`
WHERE `character_settings`.`character_id` = '1'  

तो मुझे कुछ इस तरह की आवश्यकता होनी चाहिए:

array(
    '0' => array('somekey' => 'keyname', 'value' => 'thevalue'),
    '1' => array('somekey2' => 'keyname2'),
    '2' => array('somekey3' => 'keyname3')
)

जब कुंजी 0 में डिफ़ॉल्ट मान होते हैं तो कुंजी 0 में वर्ण मान के साथ डिफ़ॉल्ट मान होता है।

जवाबों:


346

whereखंड दूर पंक्तियों जहां फ़िल्टर कर रही है left joinसफल नहीं होता। इसे शामिल होने के लिए ले जाएँ:

SELECT  `settings`.*, `character_settings`.`value`
FROM    `settings`
LEFT JOIN 
       `character_settings` 
ON     `character_settings`.`setting_id` = `settings`.`id`
        AND `character_settings`.`character_id` = '1'  

55

OUTER JOINs (ANSI-89 या ANSI-92) बनाते समय, निस्पंदन स्थान मायने रखता है क्योंकि ONक्लॉज में निर्दिष्ट मानदंड JOIN बनाने से पहले लागू किया जाता है । जोइन बनने के बादWHERE क्लॉज में प्रदान की गई OUTER जोइन टेबल के खिलाफ मानदंड लागू किया जाता है । यह बहुत भिन्न परिणाम सेट उत्पन्न कर सकता है। इसकी तुलना में, अगर यह मानदंड ONया WHEREखंड में प्रदान किया जाता है तो INNER JOIN के लिए कोई फर्क नहीं पड़ता - परिणाम समान होगा।

  SELECT  s.*, 
          cs.`value`
     FROM SETTINGS s
LEFT JOIN CHARACTER_SETTINGS cs ON cs.setting_id = s.id
                               AND cs.character_id = 1

21

यदि मैं आपके प्रश्न को सही ढंग से समझता हूं, तो आप सेटिंग्स डेटाबेस से रिकॉर्ड चाहते हैं यदि उनके पास character_settings तालिका में शामिल नहीं है या यदि रिकॉर्ड में शामिल किया गया है character_id = 1।

इसलिए आपको करना चाहिए

SELECT `settings`.*, `character_settings`.`value`
FROM (`settings`)
LEFT OUTER JOIN `character_settings` 
ON `character_settings`.`setting_id` = `settings`.`id`
WHERE `character_settings`.`character_id` = '1' OR
`character_settings`.character_id is NULL

7
यह गलत सकारात्मक लौटाने का जोखिम है
OMG पॉनीज़

1
@OMGonies मुझे समझ में नहीं आता, ऐसे मामले क्या हो सकते हैं जिनमें इसके जोखिम हैं। मेरे मामले में मैंने AND को ज्वाइन किया और कोई नतीजा नहीं निकला, लेकिन जब मैंने उपरोक्त समाधान का उपयोग किया, तो मेरे पास परिणाम थे। लेकिन मैं उन मुद्दों के बारे में सुनिश्चित होना चाहता हूं जो इस विकल्प के साथ सामना कर सकते हैं।
चेतन शर्मा

2

आपको एक सरल उपवर्ग का उपयोग करके समझना आसान हो सकता है

SELECT `settings`.*, (
    SELECT `value` FROM `character_settings`
    WHERE `character_settings`.`setting_id` = `settings`.`id`
      AND `character_settings`.`character_id` = '1') AS cv_value
FROM `settings`

उपश्रेणी को अशक्त होने की अनुमति है, इसलिए आपको मुख्य प्रश्न में JOIN / WHERE के बारे में चिंता करने की आवश्यकता नहीं है।

कभी-कभी, यह MySQL में तेजी से काम करता है , लेकिन यह देखने के लिए LEFT JOIN फॉर्म के खिलाफ तुलना करें कि आपके लिए सबसे अच्छा काम क्या है।

SELECT s.*, c.value
FROM settings s
LEFT JOIN character_settings c ON c.setting_id = s.id AND c.character_id = '1'

1

SQL कथन के आधार पर परिणाम सही है। लेफ्ट जॉइन राइट टेबल से सभी वैल्यूज रिटर्न करते हैं, और लेफ्ट टेबल से केवल मैचिंग वैल्यूज।

ID और NAME कॉलम दाईं ओर की तालिका से हैं, इसलिए वापस कर दिए गए हैं।

स्कोर बाईं तालिका से है, और 30 को लौटा दिया गया है, क्योंकि यह मान नाम "फ़्लो" से संबंधित है। अन्य नाम NULL हैं क्योंकि वे नाम "फ़्लो" से संबंधित नहीं हैं।

नीचे वह परिणाम वापस आएगा जिसकी आप अपेक्षा कर रहे थे:

    SELECT  a.*, b.Score
FROM    @Table1 a
    LEFT JOIN @Table2 b
       ON a.ID = b.T1_ID 
WHERE 1=1
AND a.Name = 'Flow'

एसक्यूएल दाहिने हाथ की मेज पर एक फिल्टर लागू करता है।


0

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

with settings_for_char as (
  select setting_id, value from character_settings where character_id = 1
)
select
  settings.*,
  settings_for_char.value
from
  settings
  left join settings_for_char on settings_for_char.setting_id = settings.id;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.