开发者

LEFT OUTER JOIN SUM doubles problem

Table: Shopping

shop_id shop_name  shop_time
1   Brian  40
2   Brian   31
3   Tom   20
4   Brian   30

Table:bananas

banana_id  banana_amount  banana_person
1    1     Brian
2    1     Brian

I now want it to print:

Name: Tom | Time: 20 | Bananas: 0

Name: Brian | Time: 101 | Bananas: 2

I used this code:

$result = dbquery("SELECT tz.*, tt.*,
SUM(shop_time) as shoptime,
count(banana_amount) as bananas

 FROM shopping tt
 LEFT OUTER JOIN bananas tz ON tt.shop_name=tz.banana_per开发者_开发技巧son
 GROUP by banana_person
LIMIT 40
");



while ($data5 = dbarray($result)) {

echo 'Name: '.$data5["shop_name"].' | Time: '.$data5["shoptime"].' | Bananas: '.$data5["bananas"].'<br>';


}

The problem is that I get this instead:

Name: Tom | Time: 20 | Bananas: 0

Name: Brian | Time: 202 | Bananas: 6

I just don't know how to get around this.


The problem is that you are constructing a cross product of the two tables which multiplies the results up by the number of rows in the opposite table. To solve this first calculate the result of aggregating one of the tables in a derived table and join this aggregated result to the other table.

SELECT
    shop_name,
    shoptime,
    IFNULL(SUM(banana_amount), 0)
FROM (
    SELECT shop_name, SUM(shop_time) as shoptime
    FROM shopping
    GROUP BY shop_name
) tt
LEFT JOIN bananas tz ON tt.shop_name=tz.banana_person
GROUP BY shop_name


Using * is the issue (since you are using group by). Also, the SUM(shop_time) is being multipled by as many rows in banaanas hence you are getting 202(for two rows in bananas)

Try this query:

SELECT tt.shop_name, 
           SUM(shop_time)           AS shoptime, 
           Ifnull(banana_amount, 0) AS bananas 
    FROM   shop tt 
           LEFT OUTER JOIN (SELECT banana_person, 
                                   SUM(banana_amount) AS banana_amount 
                            FROM   bananas 
                            GROUP  BY banana_person) tz 
             ON tt.shop_name = tz.banana_person 
    GROUP  BY shop_name; 


select
      xx.shop_name
    , xx.tot_time
    , coalesce(yy.tot_bananas, 0) as tot_bananas
from
(
    select
          shop_name
        , sum(shop_time) as tot_time
    from shopping
    group by shop_name
) as xx
left join
(
    select
          banana_person
        , sum(banana_amount) as tot_bananas
    from bananas
    group by banana_amount
) as yy on xx.shop_name = yy.banana_person
order by xx.shop_name
;
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜