Select total of childrens in multiple tables in one query with mysql

醉酒当歌 提交于 2019-12-10 19:01:33

问题


All my afternoon was consumed trying to deal with a query (or two or three) in order to get the count of all childs of three tables. Take a look to my design:

user table

id_user | name
1 | foo
2 | bar

wons table

id_won | user
1 | 1
2 | 1
3 | 2

draws table

id_draw | user
1 | 1
2 | 2
3 | 2

loses table

id_lose | user
1 | 1
2 | 1
3 | 1

I'm trying to get something like this:

name | wons | draws | loses
foo | 2 | 1 | 3
bar | 1 | 2 | 0

This is my try:

select 
    u.name, w.total_w, d.total_d, l.total_l
from 
    user u
    LEFT JOIN 
    (select count(user) as total_w, user from wons group by user) as w
    ON w.user = u.id_user
    LEFT JOIN 
    (select count(user) as total_d, user from draws group by user) as d 
    ON d.user = w.user
    LEFT JOIN 
    (select count(user) as total_l, user from loses group by user) as l 
    ON d.user= .user

group by u.id_user;

回答1:


select u.name, w.uw as wins, l.ul as loses, d.ud as draws from user
    left join (select user, COUNT(id_won) uw from wons group by user) w on w.user = u.user_id
    left join (select user, COUNT(id_lose) ul from loses group by user) l on l.user = u.user_id
    left join (select user, COUNT(id_draw) ud from draws group by user) d on d.user = u.user_id

This one would just the needed amount of work for the task.




回答2:


You can calculated their total values in a subquery and joined them on table users. I added COALESCE to show zero instead of null in the case the user is not present on the other tables.

SELECT  a.id_user,
        COALESCE(b.totalWon,0) Wons,
        COALESCE(d.totalLoses,0) Loses,
        COALESCE(c.totalDraws,0) Draws
FROM    users a
        LEFT JOIN 
        (
            SELECT `user`, COUNT(id_won) totalWon
            FROM wons
            GROUP BY `user`
        ) b ON a.id_user = b.`user`
        LEFT JOIN
        (
            SELECT `user`, COUNT(id_draw) totalDraws
            FROM draws
            GROUP BY `user`
        ) c ON a.id_user = c.`user`
        LEFT JOIN
        (
            SELECT `user`, COUNT(id_lose) totalLoses
            FROM loses
            GROUP BY `user`
        ) d ON a.id_user = d.`user`

SQLFiddle Demo




回答3:


The cleanest SQL is:

SELECT 
    u.name,
    w.wins,
    d.draws,
    l.loses
FROM
    user u
LEFT JOIN 
    (SELECT user,COUNT(*) wins FROM wons GROUP BY user) w ON w.user = u.id_user
LEFT JOIN 
    (SELECT user,COUNT(*) draws FROM draws GROUP BY user) d ON d.user = u.id_user
LEFT JOIN 
    (SELECT user,COUNT(*) loses FROM loses GROUP BY user) l ON l.user = u.id_user

See http://sqlfiddle.com/#!2/91b61/10




回答4:


I'll suggest an alternative approach which might be an overkill for your project but keeps performance in mind if you are going to generate the desired result a lot.

Create a summary table (similar to your desired output). You can empty shell record created for each user there.

Add triggers in won, draw and losses table that simply updated the data in summary table.

That's one approach. Next approach is if your desired result isn't mission critical (i.e. does not have to be an up to date thing) then consider adding a scheduled events (that run every 10 or 20 min that run the query provided above (which I've given +1 votes) and use that to update the summary table.

Best of luck!



来源:https://stackoverflow.com/questions/12649119/select-total-of-childrens-in-multiple-tables-in-one-query-with-mysql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!