是否可以在一个MySQL查询中执行此操作?

时间:2011-11-01 12:15:55

标签: php mysql

我有两张桌子:

conversation_participants

id      | conversation_id | user_id
int(11) |  int(11)        |   int(11)

用户

id      | username   | ....
int(11) | varchar(20)| ....

我正在尝试选择在用户名中具有特定字符串的所有用户,这些用户不是特定对话中的参与者。目前我有两个SQL查询:

SELECT user_id FROM conversation_participants WHERE conversation_id=?

SELECT id, username from users WHERE username LIKE '%%%{$_GET['q']}%%' ORDER BY id DESC LIMIT 10

并从第二个查询中删除与第一个查询中的user_id相同的所有结果。有没有办法将这两个查询合并为一个?

提前谢谢

5 个答案:

答案 0 :(得分:2)

SELECT id, username from users 
WHERE username LIKE '%%%{$_GET['q']}%%' 
and username not in 
(
  SELECT user_id FROM conversation_participants 
  WHERE conversation_id=users.conversation_id
)
ORDER BY id DESC LIMIT 10

不要构建连接字符串的sql语句。您应该使用某种实用方法来清理您的输入。您的陈述容易发生SQL注入攻击。

PHP有几个功能。查看mysql_real_escape_string

答案 1 :(得分:1)

除了上面的答案,我还要补充一点,你不应该在你的查询中直接使用$ _GET(etc)参数而不检查SQL注入。

答案 2 :(得分:1)

您可以使用LEFT JOIN和IS NULL

执行此操作
SELECT 
    u.id, 
    u.username 
from 
    users u
    LEFT JOIN
         conversation_participants cp 
    ON (u.id=cp.user_id AND cp.conversation_id=?)
WHERE 
    username LIKE '%%%{$_GET['q']}%%' AND
    cp.user_id IS NULL
ORDER BY id DESC LIMIT 10

我认为这比使用NOT IN()和子查询出于性能原因更为理想。

答案 3 :(得分:0)

您也可以使用JOIN,这可能会更快一些。

SELECT u.id, u.username from users u LEFT JOIN conversation_participants c ON c.user_id = u.id WHERE u.username LIKE '%%%{$_GET['q']}%%' AND c.conversation_id != ? ORDER BY u.id DESC LIMIT 10

答案 4 :(得分:0)

除了上述答案,您还可以删除表conversation_participants中的“id”字段,并将2个字段conversation_id和user_id定义为主键。