在MySQL中加入3个表

时间:2015-03-03 14:39:43

标签: php mysql

我有3张桌子。

Users

id | Name
----------
1  | Richard
2  | Mark
3  | John
4  | Victor
5  | James

Airtime

id | User_id |Amount
-------------------
1  | 1       | 40
2  | 3       | 30
3  | 4       | 47



Messages

 id | User_id |Msg
-------------------
 1  | 2       | Hello
 2  | 3       | How are You
 3  | 1       | Wassup?
 4  | 3       | Hello guys

我需要显示用户列表及其通话时间(如果他们没有显示0)以及消息计数(例如,用户ID 3有2条消息,因此它应显示2)。

我需要将结果作为

Userid | Name    |Msg Count | Airtime

     1  | Richard | 1        | 40
     2  | Mark    | 1        | 0
     3  | John    | 2        | 30
     4  | Victor  | 0        | 47
     5  | James   | 0        | 0

到目前为止,这是我尝试过的,但它仅返回同时拥有消息和播放时间的用户的结果。

SELECT 
airtime.amount AS credit, 
COUNT(messages.id) AS msgcount,
users.*
FROM `users` 
LEFT JOIN airtime ON users.id = airtime.user_id 
LEFT JOIN messagelog ON users.id = messages.by
GROUP BY messagelog.by DESC

任何帮助将不胜感激。

4 个答案:

答案 0 :(得分:2)

好吧,正如您似乎已经想到的那样,您需要在users表上进行外连接,因为您需要有关 ALL 用户的信息,无论他们是否在其他两个表中都有信息

在许多情况下,首先将问题分解为两部分是有帮助的。查找每个用户的播出时间并不太难,因为您可以按user_id对该列和组进行求和,如下所示:

SELECT u.id, COALESCE(SUM(a.amount), 0) AS totalAirtime
FROM users u
LEFT JOIN airtime a ON a.user_id = u.id
GROUP BY u.id;

Coalesce是一个返回第一个非null值的函数。因此,在这种情况下,如果用户在通话时间表中没有任何记录,则totalAirtime列将为0.

接下来,查找每个用户的消息数量有点棘手。首先,您要编写一个子查询,该子查询获取该表中每个用户的消息计数:

SELECT user_id, COUNT(*) AS numMessages
FROM messages
GROUP BY user_id;

外部将users表连接到(使用coalesce)函数,为该表中不存在的用户获取0:

SELECT u.id, COALESCE(t.numMessages, 0) AS totalMessages
FROM users u
LEFT JOIN(
  SELECT user_id, COUNT(*) AS numMessages
  FROM messages
  GROUP BY user_id) t ON t.user_id = u.id
GROUP BY u.id;

最后,您可以使用user_id列将此查询与上面的查询相关联,以获取您需要的所有值:

SELECT u.id, u.name, t1.totalMessages, t2.airtime
FROM user u
JOIN(
  SELECT u.id, COALESCE(t.numMessages, 0) AS totalMessages
  FROM users u
  LEFT JOIN(
    SELECT user_id, COUNT(*) AS numMessages
    FROM messages
    GROUP BY user_id) t ON t.user_id = u.id
  GROUP BY u.id) t1 ON t1.id = u.id
JOIN(
  SELECT u.id, COALESCE(SUM(a.amount), 0) AS totalAirtime
  FROM users u
  LEFT JOIN airtime a ON a.user_id = u.id
  GROUP BY u.id) t2 ON t2.id = t1.id;

这是一个SQL Fiddle示例,如果它可以帮助您,它还包含所有中间步骤。

答案 1 :(得分:1)

你可以这样做

select
u.id,
u.name,
COALESCE(m.cnt,0) as `count`,
COALESCE(a.Amount,0) as  Airtime
from users u
left join Airtime a on a.User_id = u.id
left join (
  select
  User_id,
  count(*) as cnt
  from Messages
  group by User_id
)m on m.User_id = u.id

<强> DEMO

答案 2 :(得分:0)

简单如下:

SELECT 
SUM(COALESCE(airtime.amount,0) ) AS credit, 
COUNT(messages.id) AS msgcount,
users.*
FROM users 
LEFT JOIN airtime ON users.id = airtime.user_id 
LEFT JOIN messages ON users.id = messages.user_id
GROUP BY users.id 
ORDER BY msgcount DESC

http://sqlfiddle.com/#!2/d77a18/6

答案 3 :(得分:0)

试试这个:

&#13;
&#13;
select u.id, u.name,
(select count(distinct m.id) from messages m where m.user_id = u.id) as 'Msg Count',
ifnull(a.amount, 0) as Airtime
from users u left join airtime a on (a.user_id = u.id);
&#13;
&#13;
&#13;