0

使用 MySQL,我想列出所有没有文档“联络员”的用户。这可能意味着根本没有任何文档的用户,或者有文档但在这些文档中没有“联络人”的用户。

如何使用 MySQL 查询?我不能让它工作!

这是(简单)模型

Users (id, name)
Documents (id, user_id, name, path)
4

6 回答 6

2

您正在寻找的正确查询是:

SELECT 
    * 
FROM 
    Users 
WHERE 
    id NOT IN (
        SELECT 
            user_id 
        FROM 
            Documents 
        WHERE 
            name = "liaison"
    )

这将达到您正在寻找的确切结果。如果特定用户没有文档,它将被列出。如果它有很多文件,其中之一是“联络”,则不会列出。

如果您想在文档名称中搜索“联络员”,请替换name = "liaison"name LIKE "%liaison%".

它基本上说:选择所有用户,例如没有名称为“liaison”的文档指向它。

于 2012-12-17T16:31:42.273 回答
2

NOT EXISTS是一个可行的解决方案。作为替代方案,有时,对于大型集合,“反 JOIN”操作可以提供更好的性能:

SELECT u.*
  FROM Users u
  LEFT
  JOIN (SELECT d.user_id
          FROM Documents d
         WHERE d.name = 'liaison'
       ) l
    ON l.user_id = u.id
 WHERE l.user_id IS NULL

别名为的内联视图l返回给我们一个包含名为“liaison”的文档的 user_id 列表;该结果集外部连接到 Users 表,然后我们排除找到匹配项的任何行(l.user_id 的测试为 NULL)。

这将返回一个与您的带有NOT EXISTS谓词的查询等效的结果集。

另一种选择是使用带有NOT IN谓词的查询。请注意,我们需要保证子查询不返回 NULL,因此一般方法是在子查询返回的列上包含一个 IS NOT NULL 谓词。

SELECT u.*
  FROM Users u
 WHERE u.id NOT IN 
       ( SELECT d.user_id 
           FROM Documents d
          WHERE d.user_id IS NOT NULL
            AND d.name = 'liaison'
       )

我会这样写NOT EXISTS查询:

SELECT u.*
  FROM Users u
 WHERE NOT EXISTS 
       ( SELECT 1
           FROM Documents d
          WHERE d.name = 'liaison'
            AND d.user_id = u.id
       )

我个人的偏好是在相关子查询的 SELECT 列表中使用文字 1;它提醒我查询只是在寻找 1 行的存在。)

同样,我通常发现“反连接”模式在大集合中表现最好。(您需要查看每个语句的 EXPLAIN 输出,并测量每个语句的性能以确定哪个最适合您的情况。)

于 2012-12-17T16:41:11.337 回答
1
select * from Users where not exists (select id from Documents where Users.id = Documents.id and Documents.name = 'liaison')
于 2012-12-17T16:17:10.000 回答
1

所以,我终于想出了这个似乎很好用的解决方案:

SELECT * FROM users u WHERE id NOT IN (SELECT DISTINCT user_id FROM user_documents WHERE name = 'LIAISON') ORDER BY c.lastname, c.firstname
于 2012-12-17T16:26:38.097 回答
1
SELECT users.*
FROM users left join Documents
     on users.id = Documents.user_id
        and documents.name='LIAISON'
WHERE documents.user_id is null
于 2012-12-17T16:30:05.173 回答
0

尝试 :

SELECT DISTINCT u.*
FROM users u LEFT JOIN documents d ON d.user_id = u.id
WHERE d.id IS NULL OR d.name NOT LIKE '%liaison%'

如果“联络”是文档的确切名称,则删除百分号。

于 2012-12-17T16:13:21.963 回答