MySQL क्वेरी के WHERE क्लॉज में कॉलम उर्फ ​​का उपयोग करना एक त्रुटि पैदा करता है


201

मैं जिस क्वेरी को चला रहा हूं वह इस प्रकार है, हालांकि मुझे यह त्रुटि मिल रही है:

# 1054 - 'IN / ALL / किसी भी उपश्रेणी' में अज्ञात कॉलम 'गारंटीकृत_पोस्टकोड'

SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE `guaranteed_postcode` NOT IN #this is where the fake col is being used
(
 SELECT `postcode` FROM `postcodes` WHERE `region` IN
 (
  'australia'
 )
)

मेरा प्रश्न है: मैं एक ही डीबी क्वेरी के क्लॉज में एक नकली कॉलम का उपयोग करने में असमर्थ क्यों हूं?

जवाबों:


434

आप केवल ग्रुप BY, ORDER BY या HAVING क्लॉस में कॉलम एलियासेस का उपयोग कर सकते हैं।

मानक SQL आपको WHERE क्लॉज में एक कॉलम उर्फ ​​को संदर्भित करने की अनुमति नहीं देता है। यह प्रतिबंध इसलिए लगाया गया है क्योंकि जब WHERE कोड निष्पादित होता है, तो स्तंभ मान अभी तक निर्धारित नहीं किया जा सकता है।

MySQL प्रलेखन से नकल की गई

जैसा कि टिप्पणियों में कहा गया है, इसके बजाय HAVING का उपयोग कार्य कर सकता है। हालांकि इस WHERE बनाम HAVING पर एक रीड देना सुनिश्चित करें ।


1
त्वरित और सटीक प्रतिक्रिया के लिए चीयर्स! मैंने HAVING क्लॉज पर एक नज़र डाली है और इस क्वेरी को सफलतापूर्वक चलाने का एक तरीका काम किया है। एक बार फिर धन्यवाद।
जेम्स

38
मामले में किसी और के पास भी वही संभावना है जो मेरे द्वारा अलियास किए गए कॉल का उपयोग कर रहा था जहां क्लॉज फेल हो रहा था - 'जहां' के लिए 'व्हाट्सएप' को स्वैप करते हुए इसे सीधे +1 अच्छा उत्तर दिया गया था।
MegaSteve4

@ MegaSteve4 मुझे भी यही समस्या थी! "HAVING" का उपयोग करके इसे आसानी से हल किया गया। :)
जोहान

9
यह आपके मामले में महत्वपूर्ण हो सकता है या नहीं, लेकिन HAVINGधीमी गति से निष्पादित करता हैWHERE
डीटीएस

1
कारण havingकाम करता है क्योंकि कॉलम मानों को आपके द्वारा प्राप्त किए जाने वाले समय तक गणना करना पड़ता है havingwhereजैसा कि ऊपर कहा गया है, ऐसा नहीं है।
मिल्ली स्मिथ

24

जैसा कि विक्टर ने बताया, समस्या उर्फ ​​के साथ है। हालांकि इससे बचा जा सकता है कि अभिव्यक्ति को सीधे WHERE x IN y क्लॉज में डालकर:

SELECT `users`.`first_name`,`users`.`last_name`,`users`.`email`,SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE SUBSTRING(`locations`.`raw`,-6,4) NOT IN #this is where the fake col is being used
(
 SELECT `postcode` FROM `postcodes` WHERE `region` IN
 (
  'australia'
 )
)

हालाँकि, मुझे लगता है कि यह बहुत ही अक्षम है, क्योंकि बाहरी क्वेरी की प्रत्येक पंक्ति के लिए सबक्वेरी को निष्पादित करना होगा।


1
@ क्रोध, हां मेरा मानना ​​है कि यह गंभीर रूप से धीमा और अक्षम है।
पचेरियर

20

मानक SQL (या MySQL) WHERE क्लॉज में कॉलम एलियास के उपयोग की अनुमति नहीं देता है क्योंकि

जब WHERE क्लॉज़ का मूल्यांकन किया जाता है, तो स्तंभ मान अभी तक निर्धारित नहीं किया जा सकता है।

( MySQL प्रलेखन से )। आप क्या कर सकते हैं जहां WHERE क्लॉज में स्तंभ मान की गणना करें , एक चर में मान को सहेजें, और फ़ील्ड सूची में इसका उपयोग करें। उदाहरण के लिए आप ऐसा कर सकते हैं:

SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
@postcode AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE (@postcode := SUBSTRING(`locations`.`raw`,-6,4)) NOT IN
(
 SELECT `postcode` FROM `postcodes` WHERE `region` IN
 (
  'australia'
 )
)

यह जटिल होने पर अभिव्यक्ति को दोहराने से बचता है, जिससे कोड को बनाए रखना आसान हो जाता है।


9
क्या यह विरोधाभास दस्तावेज़ीकरण के साथ नहीं है जो कहता है कि "एक सामान्य नियम के रूप में, आपको कभी भी किसी उपयोगकर्ता चर का मान निर्दिष्ट नहीं करना चाहिए और उसी कथन के भीतर मान को पढ़ना चाहिए। आपको अपेक्षित परिणाम मिल सकते हैं, लेकिन इसकी गारंटी नहीं है।" ?
अर्जन

यह निश्चित रूप से कुछ को ध्यान में रखना है। यह हमेशा मेरे लिए काम किया है, हालांकि, मुझे लगता है कि एक बयान के विभिन्न हिस्सों के मूल्यांकन का क्रम तय किया जाना था (पहले WHERE, फिर चयन, फिर ग्रुप BY, ...) लेकिन मेरे पास इसके लिए कोई संदर्भ नहीं है।
जोनी

कुछ उदाहरण: कुछ का दावा है कि उनके लिए select @code:=sum(2), 2*@codeMySQL 5.5 में काम करता है, लेकिन मेरे लिए 5.6 में दूसरा कॉलम पहले आह्वान पर NULL देता है, और फिर से चलने पर पिछले परिणाम का 2 गुना रिटर्न देता है । काफी दिलचस्प, दोनों का चयन करें @code:=2, 2*@codeऔर select @code:=rand(), 2*@codeमेरे 5.6 (आज) में काम करने लगते हैं। लेकिन वे वास्तव में चयन खंड में लिख रहे हैं और पढ़ रहे हैं; आपके मामले में आप इसे WHERE में सेट कर रहे हैं।
अर्जन

@ जोनी, सिर्फ दो बार हालत का मूल्यांकन क्यों नहीं? निश्चित रूप से MySQL स्मार्ट है कि अनुकूलन के लिए .......
Pacerier

@Pacer की अभिव्यक्ति को दोहराने के लिए अभी भी बदतर है खासकर अगर यह जटिल है। अगर MySQL सामान्य सबप्रेसेशन एलिमिनेशन को लागू करता है तो मैं पुष्टि नहीं कर सकता।
जोनी

16

हो सकता है कि मेरा उत्तर बहुत देर से आया हो लेकिन इससे दूसरों को मदद मिल सकती है।

आप इसे किसी अन्य चुनिंदा विवरण के साथ संलग्न कर सकते हैं और इसका उपयोग उस स्थान पर कर सकते हैं जहां खंड है।

SELECT * FROM (Select col1, col2,...) as t WHERE t.calcAlias > 0

कैल्कियालस उपनाम स्तंभ है जिसकी गणना की गई थी।


अच्छा और छोटा, लेकिन यह उपयोगी होने के लिए बहुत अस्पष्ट है।
अगामेन्नुस

@ एगैम्नस, आपका क्या मतलब है?
पचेरियर

सवाल था, "मैं उसी DB क्वेरी के क्लॉज़ में नकली कॉलम का उपयोग करने में असमर्थ क्यों हूं?" यह उत्तर उस प्रश्न का उत्तर नहीं देता है और एक क्रिया को याद कर रहा है।
अगम्मेन्नुस

तो बस
HAVING का

8

आप सेलेक्ट फ़ील्ड और उपनाम में गणना की गई फ़िल्टर के लिए HAVING क्लॉज़ का उपयोग कर सकते हैं


@ fahimg23 - निश्चित नहीं है। मैंने एक कारण खोजने की कोशिश की, लेकिन मैं नहीं कर सकता! हालांकि WHEREऔर HAVING, के बीच के मतभेदों को ध्यान में रखें । वे समान नहीं हैं। stackoverflow.com/search?q=where+vs+having
rinogo

अद्यतन: यह इसलिए है क्योंकि यह उत्तर एक ही समाधान प्रदान करता है लेकिन अधिक जानकारी के साथ।
रिनोगो

1

मैं mysql 5.5.24 का उपयोग कर रहा हूं और निम्नलिखित कोड काम करता है:

select * from (
SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
) as a
WHERE guaranteed_postcode NOT IN --this is where the fake col is being used
(
 SELECT `postcode` FROM `postcodes` WHERE `region` IN
 (
  'australia'
 )
)

0

मानक SQL WHERE क्लॉज में कॉलम उपनामों को संदर्भित करता है। यह प्रतिबंध इसलिए लगाया गया है क्योंकि जब WHERE क्लॉज़ का मूल्यांकन किया जाता है, तो स्तंभ मान अभी तक निर्धारित नहीं किया जा सकता है। उदाहरण के लिए, निम्नलिखित प्रश्न अवैध है:

Id का चयन करें, COUNT (*) AS cnt से tbl_name जहां cnt> 0 GROUP BY आईडी;


0

आप जहां कंडिटोन के लिए SUBSTRING ( locationsraw, -6,4) का उपयोग कर सकते हैं

SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE SUBSTRING(`locations`.`raw`,-6,4) NOT IN #this is where the fake col is being used
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN
(
 'australia'
)
)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.