[英]How to write better this Mysql Join query
我有下一张桌子
Users {id, name}
Messages {id, user_id, cache_user_name}
我想要的是仅出于性能原因在cache_user_name为NULL时执行JOIN。
例如:
SELECT Messages.*, Users.name FROM Messages INNER JOIN Users ON (Messages.user_id = Users.id)
// ON (ISNULL(Messages.cache_user_name) AND ...
最好的方法是执行2个查询? 1用于没有缓存(联接)的行,另一用于具有联接的缓存行?
[编辑]
我需要的结果是:
用户数
ID: 1, NAME: Wiliam
留言内容
ID: 1, USER_ID: 1, CACHE_USER_NAME: Wiliam
ID: 2, USER_ID: 1, CACHE_USER_NAME: null
结果
ID: 1, USER_ID: 1, CACHE_USER_NAME: Wiliam, USERS.NAME: null // No join, faster
ID: 2, USER_ID: 1, CACHE_USER_NAME: null, USERS.NAME: Wiliam // Join
您可以添加WHERE ... IS NULL
子句。
优化器将(尝试)使用性能最佳的计划。
SELECT Messages.*
, Users.name
FROM Messages
INNER JOIN Users ON (Messages.user_id = User.id)
WHERE Users.cache_user_name IS NULL
给定以下数据,您期望输出什么?
DECLARE @Users TABLE (ID INTEGER, Name VARCHAR(32))
DECLARE @Messages TABLE (ID INTEGER, User_ID INTEGER, Cache_User_Name VARCHAR(32))
INSERT INTO @Users VALUES (1, 'Wiliam')
INSERT INTO @Users VALUES (2, 'Lieven')
INSERT INTO @Users VALUES (3, 'Alexander')
INSERT INTO @Messages VALUES (1, 1, NULL)
INSERT INTO @Messages VALUES (2, 1, 'Cached Wiliam')
INSERT INTO @Messages VALUES (3, 2, NULL)
INSERT INTO @Messages VALUES (4, 3, 'Cached Alexander')
SELECT *
FROM @Users u
INNER JOIN @Messages m ON m.User_ID = u.ID
WHERE m.Cache_User_name IS NULL
SELECT m.Id, m.user_id, CACHE_USER_NAME user_name
FROM messages m
WHERE CACHE_USER_NAME IS NOT NULL
UNION ALL
SELECT m.Id, m.user_id, u.user_name user_name
FROM (Select * from messages Where cache_user_name IS NULL) m
JOIN users ON (u.user_id = m.user_id)
无论如何,最好的方法是在创建消息期间将cache_user_name存储在表消息中。 然后,您将完全需要加入。
我认为这些与以前的答案一起使用Not Null where子句应该可以正常工作,但也许我们没有关注您的效率低下问题。 只要对users.id和messages.user_id进行了索引并且具有相同的类型,那么除非您拥有庞大的用户数据库和大量消息,否则该联接不会很慢。 如果有的话,扔更多的硬件; 可能您正在运行大量流量并负担得起。 :)
另外,您也可以这样处理:对名称不为null的消息进行查询,遍历结果,查找每条消息的名称(并将它们放入数组中),然后在用户表中查询那些名称名称。 然后,当您遍历“消息”结果时,可以显示您保存的阵列中的正确名称。 您将有两个查询,但是它们很快。
$users = $messages = $users_ids = array ();
$r = mysql_query('select * from Messages where cache_user_name is not null');
while ( $rs = mysql_fetch_array($r, MYSQL_ASSOC) )
{
$user_ids[] = $rs['user_id'];
$messages[] = $rs;
}
$user_ids = implode ( ',', $user_ids );
$u = mysql_query("select * from Users where id in ($users)");
while ( $rs = mysql_fetch_array($r, MYSQL_ASSOC) )
{
$users[$rs['id']] = $rs['name'];
}
foreach ( $messages as $message )
{
echo "message {$message['id']} authored by " . $users[$message['user_id']] . "<br />\n";
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.