【问题标题】:MySQL replace UNION with LEFT JOIN IFNULLMySQL 用 LEFT JOIN IFNULL 替换 UNION
【发布时间】:2015-11-28 03:47:41
【问题描述】:

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

我们有一个用户表和一个令牌表,它们都需要 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)

到目前为止,我所做的只是做一个 RIGHT JOIN 之类的

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 中的 temptable 和庞大的用户量,这将迫使 MySQL 编写一个至少超过 10.000 条记录的 temp 表

【问题讨论】:

  • 10,000 条记录的临时表不是很大。如果union all 做你想做的事,那就走那条路。
  • UNION 总共需要 20 多秒,所以与 UNION 呆在一起肯定太长了
  • 您确定问题出在 UNION 查询上吗?还是(某些连接)会使查询变慢?
  • 它与UNION ALL 一起工作是否更好,因此它不会尝试删除重复项?
  • UNION 走错路了!

标签: mysql performance join union


【解决方案1】:
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、用户、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;

【讨论】:

  • 你好 Rick,谢谢你的目的,但是那个查询并没有真正给我我需要的结果集。结果的结构是不可改变的。我需要一个 id、用户名、密码字段结构。连接标记并没有给我正确的结构。该表稍后被另一个需要该表结构的工具使用
  • 我认为没有真正的方法可以防止加入。您的编辑也会遗漏原始密码(如果存在)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 2018-02-28
  • 1970-01-01
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多