एक चयनित उपकुंजी से कई कॉलम प्राप्त करें


24
SELECT 
   *, 
   p.name AS name, 
   p.image, 
   p.price,
   ( 
       SELECT ps.price 
       FROM product_special ps 
       WHERE p.id = ps.id
         AND ps.date < NOW() 
       ORDER BY ps.priority ASC, LIMIT 1
   ) AS special_price,
   ( 
       SELECT ps.date 
       FROM product_special ps 
       WHERE p.id = ps.id
         AND ps.date < NOW() 
       ORDER BY ps.priority ASC, LIMIT 1
   ) AS date
FROM product p LEFT JOIN product_special ps ON (p.id = ps.id)

जैसा कि आप देख सकते हैं कि मैं एक ही कॉलम को बाहर निकालने के लिए उसी उपश्रेणी को दोहरा रहा हूं। मुझे आश्चर्य है कि ऐसा करने का एक बेहतर तरीका है?

आईडी दोनों तालिकाओं में प्राथमिक कुंजी है। अगर मुझे मदद मिल सकती है तो मुझे product_special.priority को बनाने में कोई समस्या नहीं है ।

जवाबों:


11

मान लेना संयोजन product_special.id, product_special.priorityअद्वितीय है

 SELECT p.*, special_price,special_date
 FROM product p
 LEFT JOIN 
 (
     SELECT ps.id, ps.price as special_price, ps.`date` as special_date
     FROM product_special ps
     INNER JOIN 
     (
       SELECT id, MIN(priority) as min_priority 
       FROM product_special
       GROUP BY id
     ) ps2 
     ON (ps2.id = ps.id)
 )a ON (a.id=p.id)

5

जब तक आप फ़ील्ड को special_price.price और date.date के रूप में वापस करने का इरादा नहीं रखते हैं, तब तक उप-नाम के अंदर उपनाम क्यों नहीं? जैसे

SELECT p.*, p.name AS  name, p.image, p.price, ps.*
FROM product p
LEFT JOIN
   (SELECT
      psi.price as special_price, psi.date as my_date 
    FROM product_special psi
    WHERE 
      p.id = psi.id AND
      psi.date < NOW()
    ORDER BY psi.priority ASC, LIMIT 1
   ) AS ps ON
  p.id = ps.id

क्या आपकी क्वेरी भाषा में एक FIRST () कुल फ़ंक्शन है? सुनिश्चित नहीं हैं कि आप id और प्राथमिकता (दोनों ASC सॉर्ट) के बीच product_special के एक समग्र बना सकते हैं और ORDER क्लॉज को बदल सकते हैंGROUP BY id, psi.priority

आप पूरी तरह से खंड द्वारा आदेश को हटाने और उपयोग करने में सक्षम हो HAVING MIN(psi.priority)


2

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

left join highestPriorityProductSpecial(p.id) on true

ठीक है, लेकिन नहीं

left join (select * from product_special ps where ps.id = p.id order by priority desc limit 1) on true

भले ही फ़ंक्शन की परिभाषा ठीक यही है।

तो, यह वास्तव में एक आसान समाधान है (9.1 में कम से कम): फ़ंक्शन के अंदर सीमा को करके अपनी सर्वोच्च प्राथमिकता पंक्ति निकालने के लिए एक फ़ंक्शन बनाएं।

लेकिन फ़ंक्शंस में दोष यह है कि क्वेरी प्लान यह नहीं दिखाएगा कि उनके अंदर क्या चल रहा है और मुझे विश्वास है कि यह हमेशा नेस्टेड लूप जॉइन करेगा, भले ही वह सर्वश्रेष्ठ न हो।


6
cross apply है (2013 में जारी) 9.3 के साथ शुरू Postgres में उपलब्ध हैं, लेकिन वे एसक्यूएल मानक का पालन और मानक का उपयोग करने के लिए चुना lateralऑपरेटर। अपनी दूसरी क्वेरी left joinleft join lateral
a_horse_with_no_name

2

निम्न SQL कमांड आज़माएं:

SELECT p.name,p.image,p.price,pss.price,pss.date
FROM Product p OUTER APPLY(SELECT TOP(1)* 
FROM ProductSpecial ps
WHERE p.Id = ps.Id ORDER BY ps.priority )as pss

1
क्या आप कृपया अपने उत्तर में अधिक जानकारी जोड़ सकते हैं
अहमद अबुस्सना

प्रश्न का कोड उपयोग करता है LIMITऔर इसे DBMS के साथ टैग नहीं किया जाता है (इसलिए यह MySQL या Postgres या SQLite या संभवतः कुछ अन्य dbms हो सकता है)। उत्तर में कोड का उपयोग करता है OUTER APPLYऔर TOPइसलिए यह SQL सर्वर (और Sybase) में ही काम करेगा जिसके पास नहीं है LIMIT
ypercube y

यह एक sql सर्वर के लिए लागू है केवल अन्य डेटाबेस के लिए हम चुनिंदा कथन के भीतर आंतरिक क्वेरी का उपयोग कर सकते हैं।
सन्तोष उपासना

Postgres में नहीं है OUTER APPLY, लेकिन LATERAL है , जो समकक्ष होना चाहिए। इसका उपयोग करने वाला एक उदाहरण: stackoverflow.com/a/47926042/4850646
लुकास बासेरनोटो नोव

2

Dezso के जवाब से प्रेरित होकर /dba//a/222471/127433 मैं इस तरह से सरणियों का उपयोग करके PostgreSQL में समस्या को हल कर रहा हूं:

SELECT 
   *, 
   p.name AS name, 
   p.image, 
   p.price,
   ( 
       SELECT ARRAY[ps.price, ps.date]
       FROM product_special ps 
       WHERE p.id = ps.id
         AND ps.date < NOW() 
       ORDER BY ps.priority ASC, LIMIT 1
   ) AS special_price_and_date
FROM product p LEFT JOIN product_special ps ON (p.id = ps.id)

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


1

मैं बस इसे अंतिम उपाय के लिए यहां रखना चाहता हूं, उन सभी के लिए जो डेटाबेस इंजन का उपयोग करते हैं जो एक या अधिक अन्य उत्तरों का समर्थन नहीं करते हैं ...

आप कुछ का उपयोग कर सकते हैं जैसे:

SELECT (col1 || col2) as col3 

(विभाजक, या स्वरूपण col1 और col2 से विशिष्ट लंबाई के साथ।) और बाद में उप-स्ट्रिंग्स का उपयोग करके अपने डेटा को ड्रा करें।

मुझे आशा है कि किसी को यह उपयोगी लगता है।


0

Z / OS के लिए DB2 में, सबसेलेक्ट में कई कॉलम वापस करने के लिए उपयोग packऔर unpackफ़ंक्शंस।

SELECT 
   *, 
   p.name AS name, 
   p.image, 
   p.price,
    unpack((select PACK (CCSID 1028,
               ps.price,
               ps.date)
         FROM product_special ps 
       WHERE p.id = ps.id
         AND ps.date < NOW() 
       ORDER BY ps.priority ASC, LIMIT 1)) .* AS (SPECIAL_PRICE double, DATE date)
FROM product p LEFT JOIN product_special ps ON (p.id = ps.id);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.