更好地查询联合连接

时间:2015-01-21 03:28:54

标签: mysql

表成员

id primary key
username varchar

table mpoints

id primary key
money int
member_id foreign key

表gpoints

id primary key
price int
member_id foreign key

mpointsgpoints几乎与members表格相同,我需要找出moneyprice之和的数据> 200&count> 2,这是我的解决方案

SELECT
    `t`.`username`, `t`.`p`
FROM
(
    SELECT
        `members`.`username`,
        `price` AS `p`
    FROM
        `members`
        LEFT JOIN `gpoints` ON `members`.`id` = `gpoints`.`member_id`
    UNION ALL
    SELECT
        `members`.`username`,
        `money` AS `p`
    FROM
        `members`
        LEFT JOIN `mpoints` ON `members`.`id` = `mpoints`.`member_id`
) AS `t`
GROUP BY `t`.`username`
HAVING COUNT(`t`.`p`) >= 2 AND `t`.`p` > 200

但是会员超过五百万,两个积分表都超过五万,所以查询速度很慢,我可以通过调整查询来提高性能吗?

2 个答案:

答案 0 :(得分:2)

我只会将gpoints和mpoints表联合起来,按该联合的member_id分组,并将该数据集加入到成员表中:

select
    m.username,
    t.p
from members as m
    inner join (
               select
                   p.member_id,
                   sum(p) as p
               from (
                    select
                        member_id,
                        price as p
                    from gpoints
                    union all
                    select
                        member_id,
                        money as p
                    from mpoints
                    ) as p
               group by
                   member_id
               having
                   count(p.p) >=2
                   and sum(p.p) > 200     
               ) t
           on t.member_id = m.id

或者,您可以为每个表添加一个分组并添加这些总和:

select
    m.username,
    gp.p + mp.p as p
from members as m
    left join (
               select
                   member_id,
                   sum(price) as p,
                   count(price) as cnt
               from gpoints
               group by member_id
               ) gp
        on gp.member_id = m.id
    left join (
               select
                   member_id,
                   sum(money) as p,
                   count(money) as cnt
               from mpoints
               group by member_id
               ) mp
        on mp.member_id = m.id
where
    ifnull(gp.p,0) + ifnull(mp.p,0) > 200
    and ifnull(gp.cnt,0) + ifnull(mp.cnt,0) >= 2

答案 1 :(得分:0)

您的正确查询将是:

SELECT t.username, SUM(t.p) as p
FROM (SELECT m.username, price AS p
      FROM members m LEFT JOIN 
           gpoints g
           ON m.id = g.member_id
      UNION ALL
      SELECT m.username, `money` AS p
      FROM members m LEFT JOIN 
           mpoints p
           ON m.id = p.member_id
     ) t
GROUP BY t.username
HAVING COUNT(t.p) >= 2 AND SUM(t.p) > 200;

请注意SUM()SELECT中使用HAVING

为了获得更好的性能,您需要gpoints(member_id, price)mpoints(member_id, money)上的索引。