Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

MySQL:SUM () जॉइन के साथ गलत मान देता है

इस क्वेरी को आजमाएं:

SELECT bl.user_id, SUM( ph.amount ) PAIDOUT
FROM (
   SELECT distinct blocks.user_id 
   FROM blocks
   WHERE confirms > 520
) bl
LEFT JOIN  payout_history ph
ON bl.user_id = ph.user_id
GROUP BY ph.user_id
;

SQLFiddle --> http://sqlfiddle.com/#!2/7b988/48



-- संपादित करें --- एक स्पष्टीकरण कि क्वेरी कैसे काम करती है (या आपकी क्वेरी क्यों काम नहीं करती है) ----

अपेक्षित परिणामों को देखते हुए ऐसा लगता है कि क्वेरी को राशि के योग की गणना करनी चाहिए प्रत्येक user_id . के लिए कॉलम , लेकिन केवल उन user_id . के लिए , जो कि ब्लॉकों . में भी हैं तालिका, और एक blocks.confirms . रखें मान 520 से अधिक है। तालिका में एक ही user_id . के लिए कई रिकॉर्ड हो सकते हैं , उदाहरण के लिए एक क्वेरी जो केवल user_id=110 . के लिए पंक्तियां लौटाती है निम्नलिखित परिणाम देता है:

SELECT *
FROM blocks
WHERE confirms > 520
      AND user_id = 110;

+ ------- + ------------ + ----------- + ------------- +
| id      | user_id      | reward      | confirms      |
+ ------- + ------------ + ----------- + ------------- +
| 0       | 110          | 20.89832115 | 521           |
| 65174   | 110          | 3.80357075  | 698           |
| 65204   | 110          | 4.41933060  | 668           |
| 65218   | 110          | 4.69059801  | 654           |
| 65219   | 110          | 4.70222521  | 653           |
| 65230   | 110          | 4.82805490  | 642           |
| 65265   | 110          | 5.25058079  | 607           |
| 65316   | 110          | 6.17262650  | 556           |
+ ------- + ------------ + ----------- + ------------- +

स्ट्रैघ जॉइन (और लेफ्ट/राइट आउटर जॉइन) इस तरह से काम करता है, जो पहली जॉइन की गई टेबल से प्रत्येक रिकॉर्ड लेता है, और इस रिकॉर्ड को दूसरी जॉइन की गई टेबल की सभी पंक्तियों के साथ पेयर करता है, जिससे जॉइन कंडीशन को पूरा किया जाता है।

हमारे मामले में लेफ्ट जॉइन एक नीचे परिणाम देता है:

SELECT *
FROM blocks
LEFT JOIN payout_history
ON blocks.user_id = payout_history.user_id
WHERE confirms > 520
    AND blocks.user_id = 110;
+ ------- + ------- + ----------- + -------- + --- + ------- + ----------- +
| id      | user_id | reward      | confirms | id  | user_id | amount      |
+ ------- + ------- + ----------- + -------- + --- + ------- + ----------- +
| 0       | 110     | 20.89832115 | 521      | 1   | 110     | 20.898319   |
| 65174   | 110     | 3.80357075  | 698      | 1   | 110     | 20.898319   |
| 65204   | 110     | 4.41933060  | 668      | 1   | 110     | 20.898319   |
| 65218   | 110     | 4.69059801  | 654      | 1   | 110     | 20.898319   |
| 65219   | 110     | 4.70222521  | 653      | 1   | 110     | 20.898319   |
| 65230   | 110     | 4.82805490  | 642      | 1   | 110     | 20.898319   |
| 65265   | 110     | 5.25058079  | 607      | 1   | 110     | 20.898319   |
| 65316   | 110     | 6.17262650  | 556      | 1   | 110     | 20.898319   |
+ ------- + ------- + ----------- + -------- + --- + ------- + ----------- +

और अब अगर हम SUM(राशि) .... GROUP BY user_id . जोड़ते हैं , MySql सभी राशि के योग की गणना करेगा उपरोक्त परिणाम से मान (8 पंक्तियाँ * 20.898 =~ 167.184 )

SELECT blocks.user_id, sum( amount)
FROM blocks
LEFT JOIN payout_history
ON blocks.user_id = payout_history.user_id
WHERE confirms > 520
    AND blocks.user_id = 110
GROUP BY blocks.user_id;
+ ------------ + ----------------- +
| user_id      | sum( amount)      |
+ ------------ + ----------------- +
| 110          | 167.186554        |
+ ------------ + ----------------- +



जैसा कि आप इस मामले में देख सकते हैं कि जॉइन हमें वांछित परिणाम नहीं देता है - हमें एक सेमी जॉइन नाम की कोई चीज़ चाहिए - सेमी जॉइन के विभिन्न प्रकार नीचे दिए गए हैं, उन्हें आज़माएं:

SELECT bl.user_id, SUM( ph.amount ) PAIDOUT
FROM (
   SELECT distinct blocks.user_id 
   FROM blocks
   WHERE confirms > 520
) bl
LEFT JOIN  payout_history ph
ON bl.user_id = ph.user_id
GROUP BY ph.user_id
;


SELECT ph.user_id, SUM( ph.amount ) PAIDOUT
FROM payout_history ph
WHERE ph.user_id IN (
     SELECT user_id FROM blocks
     WHERE confirms > 520
  )
GROUP BY ph.user_id
;

SELECT ph.user_id, SUM( ph.amount ) PAIDOUT
FROM payout_history ph
WHERE EXISTS (
     SELECT 1 FROM blocks bl
     WHERE bl.user_id = ph.user_id
        AND bl.confirms > 520
  )
GROUP BY ph.user_id
;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. java.sql.SQLException:jdbc के लिए कोई उपयुक्त ड्राइवर नहीं मिला:mysql:// localhost:3306/dbname

  2. संबंधित टैग खोजों के लिए MYSQL डेटाबेस सेट करने का सही तरीका?

  3. PHP डेटाबेस कनेक्शन वर्ग

  4. pdo निष्पादन में एक ही पैरामीटर मान को कई बार असाइन करना

  5. Doctrine2 क्वेरी बिल्डर में चेनिंग orX