Prøv denne forespørgsel:
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
--- EDIT --- en forklaring på, hvordan forespørgslen fungerer (eller rettere hvorfor din forespørgsel ikke virker) ----
Ser man på forventede resultater, ser det ud til, at forespørgslen skal beregne en sum af amount
kolonne for hver user_id
, men kun for disse user_id
, som også er i blocks
tabel, og har en blocks.confirms
værdi større end 520.
En simpel joinforbindelse (også venstre ydre joinforbindelse) kan ikke fungere i dette tilfælde, fordi blocks
tabel kan indeholde mange poster for det samme user_id
, for eksempel en forespørgsel, der kun returnerer rækker for user_id=110
giver følgende resultater:
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 |
+ ------- + ------------ + ----------- + ------------- +
Den lige joinforbindelse (og LEFT/RIGHT ydre joinforbindelse) fungerer på denne måde, der tager hver post fra den første sammenføjede tabel, og parrer denne post (kombiner den) med alle rækker fra den anden sammenføjede tabel, der opfylder joinbetingelsen.
I vores tilfælde producerer venstre joinforbindelse et nedenstående resultatsæt:
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 |
+ ------- + ------- + ----------- + -------- + --- + ------- + ----------- +
og nu hvis vi tilføjer SUM( amount ) .... GROUP BY user_id
, vil MySql beregne en sum af alt amount
værdier fra ovenstående resultatsæt (8 rækker * 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 |
+ ------------ + ----------------- +
Som du ser i dette tilfælde giver joinforbindelsen os ikke de ønskede resultater - vi har brug for noget der hedder a semi join
- nedenfor er forskellige varianter af semi joins, prøv dem:
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
;