/ / mysql दो फ़ंक्शन के साथ क्वेरी में mysql कुल कार्य अप्रत्याशित परिणाम देता है - mysql, जॉइन, एग्रीगेट-फ़ंक्शंस

mysql दो कार्यों के साथ क्वेरी में कुल कार्य अप्रत्याशित परिणाम देता है - mysql, join, समुच्चय-कार्य

निम्नलिखित (बहुत सरलीकृत) mysql तालिका संरचना को देखते हुए:

उत्पादों

  • आईडी

उत्पाद श्रेणियाँ

  • आईडी
  • उत्पाद आइ डि
  • स्थिति (पूर्णांक)

product_tags

  • आईडी
  • उत्पाद आइ डि
  • some_other_numeric_value

मैं हर उस उत्पाद को खोजने की कोशिश कर रहा हूं, जिसका एक निश्चित product_tag से जुड़ाव है, और यह कि कम से कम एक श्रेणी के संबंध जो कि स्टेटस-विशेषता 1 है।

मैंने निम्नलिखित प्रश्न का प्रयास किया:

SELECT *

FROM `product` p

JOIN `product_categories` pc
ON p.`product_id` = pc.`product_id`

JOIN `product_tags` pt
ON p.`product_id` = pt.`product_id`

WHERE pt.`some_value` = "some comparison value"

GROUP BY p.`product_id`

HAVING SUM( pc.`status` ) > 0

ORDER BY SUM( pt.`some_other_numeric_value` ) DESC

अब मेरी समस्या है: द SUM(pt.some_other_numeric_value) अप्रत्याशित मान देता है।

मैंने महसूस किया कि यदि उत्पाद में प्रश्न अधिक है तो इसका संबंध किससे है उत्पाद श्रेणियाँ तालिका, फिर हर संबंध product_tags तालिका को ऐसे समय के रूप में गिना जाता है जैसे संबंध हैं उत्पाद श्रेणियाँ टेबल!

उदाहरण के लिए: यदि id = 1 वाले उत्पाद का id_ 2, 3 और 4 के साथ product_categories के साथ संबंध है, और id_ 5 के साथ product_tags के साथ 5 और 6 के साथ संबंध है - तो अगर मैं एक सम्मिलित करता हूं GROUP_CONCAT(pt.id), तो यह देता है 5,6,5,6,5,6 अपेक्षित के बजाय 5,6.

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

क्या कोई मुझे समझा सकता है कि वास्तव में यहाँ क्या गलत हो रहा है?

उत्तर:

जवाब के लिए 5 № 1

आप "मुख्य" में शामिल हों (product) टेबल से दो टेबल (tags तथा categories) के जरिए 1:n रिश्तों, तो यह उम्मीद है, आप कर रहे हैंएक मिनी कार्टेसियन उत्पाद बनाना। उन उत्पादों के लिए जिनके पास एक से अधिक संबंधित टैग और एक से अधिक संबंधित श्रेणियां हैं, परिणाम सेट में कई पंक्तियाँ बनाई गई हैं। यदि आप Group By, आपके पास कुल कार्यों में गलत परिणाम हैं।


इससे बचने का एक तरीका यह है कि आप दोनों में से किसी एक को हटा दें, जो कि एक वैध शुरुआत है, यदि आपको उस तालिका से "टी की जरूरत नहीं है। कहो तो आपको कुछ भी नहीं चाहिए।" SELECT से सूची product_categories तालिका। तब आप सेमी-ज्वाइन (a) का उपयोग कर सकते हैं EXISTS subquery)उस तालिका में:

SELECT p.*,
SUM( pt.`some_other_numeric_value` )

FROM `product` p

JOIN `product_tags` pt
ON p.`product_id` = pt.`product_id`

WHERE pt.`some_value` = "some comparison value"

AND EXISTS
( SELECT *
FROM product_categories pc
WHERE pc.product_id = pc.product_id
AND  pc.status = 1
)

GROUP BY p.`product_id`

ORDER BY SUM( pt.`some_other_numeric_value` ) DESC ;

इस समस्या को दरकिनार करने का एक और तरीका है - के बाद GROUP BY MainTable.pk - उपयोग करने के लिए DISTINCT के अंदर COUNT() या GROUP_CONCAT() कुल कार्य। यह काम करता है लेकिन आप इसे "t" के साथ उपयोग कर सकते हैं SUM()। तो, यह आपकी विशिष्ट क्वेरी में उपयोगी नहीं है।


एक तीसरा विकल्प - जो हमेशा काम करता है - दो (या अधिक) साइड टेबल द्वारा पहले समूह में आता है और फिर मुख्य तालिका में शामिल होता है। आपके मामले में कुछ इस तरह:

SELECT p.* ,
COALESCE(pt.sum_other_values, 0) AS sum_other_values
COALESCE(pt.cnt, 0) AS tags_count,
COALESCE(pc.cnt, 0) AS categories_count,
COALESCE(category_titles, "") AS category_titles

FROM `product` p

JOIN
( SELECT product_id
, COUNT(*) AS cnt
, GROUP_CONCAT(title) AS category_titles
FROM `product_categories` pc
WHERE status = 1
GROUP BY product_id
) AS pc
ON p.`product_id` = pc.`product_id`

JOIN
( SELECT product_id
, COUNT(*) AS cnt
, SUM(some_other_numeric_value) AS sum_other_values
FROM `product_tags` pt
WHERE some_value = "some comparison value"
GROUP BY product_id
) AS pt
ON p.`product_id` = pt.`product_id`

ORDER BY sum_other_values DESC ;

The COALESCE() कड़ाई से वहाँ की जरूरत नहीं है - बस के मामले में आप भीतरी जुड़नार chnage करने के लिए LEFT बाहरी जोड़।


जवाब के लिए 0 № 2

आप एक राशि समारोह द्वारा आदेश नहीं कर सकते

इसके बजाय आप ऐसा कर सकते थे

 SELECT * ,SUM( pt.`some_other_numeric_value` ) as sumvalues

FROM `product` p

JOIN `product_categories` pc
ON p.`product_id` = pc.`product_id`

JOIN `product_tags` pt
ON p.`product_id` = pt.`product_id`

WHERE pt.`some_value` = "some comparison value"

GROUP BY p.`product_id`

HAVING SUM( pc.`status` ) > 0

ORDER BY sumvalues DESC