MySQL用LEFT JOIN IFNULL替换UNION

时间:2015-09-02 14:52:59

标签: mysql performance join union

对不起标题,但我找不到更好的描述我们的问题。

我们有一个用户表和一个令牌表,它们都需要UNIONt到一个表中,但出于性能原因没有UNION ALL。

表结构如下:

Table USER:
ID Username Password

Table TOKEN:
ID User_ID Token Token_Secret

我们现在需要的是两个表的结合。

用户始终在场,用户在大多数情况下拥有1个或多个令牌(1:N)。结果表应包含

ID Username Password

所有用户(他们是否有令牌),如果用户有令牌,则所有用户

因此,对于UNION,结果将是

SELECT * FROM user WHERE (SOME JOINS TO GET THE RIGHT USERS)
UNION ALL
SELECT Token as Username, Token_Secret AS Password FROM token WHERE (SOME JOINS TO GET THE RIGHT TOKENS)

到目前为止我尝试的只是像

那样进行正确的加入
SELECT IFNULL(b.Token, a.Username, b.Token) ... FROM 
(SELECT * FROM user WHERE (SOME JOINS)) AS a
RIGHT JOIN
(SELECT * FROM token WHERE (SOME JOINS)) AS b
ON 
b.User_ID = a.ID

但是在这种情况下,我将获得所有用户,它们没有令牌(所以我从用户表中获取用户名,密码)或者只是来自令牌表的令牌..但我需要的是两者!如果用户还有令牌,我需要用户名,密码和所有令牌(重命名为用户名,密码)

没有UNION有没有办法做到这一点? UNION的问题是MySQL和大量用户的临时性,这将迫使MySQL编写一个至少有超过10.000条记录的临时表

1 个答案:

答案 0 :(得分:0)

SELECT u.id, u.user_name,
       GROUP_CONCAT(t.token) AS tokens
    FROM users u
    LEFT JOIN tokens t ON t.user_id = u.id
    GROUP BY u.id;

如果您需要id,user,token:

SELECT u.id, u.user_name,
       IFNULL(t.token, '(no token for this user)') as token
    FROM users u
    LEFT JOIN tokens t ON t.user_id = u.id
    ORDER BY user_name, token;