Join 在sql条件下使用表而不将该表的内容合并到结果中

Join 在sql条件下使用表而不将该表的内容合并到结果中,join,sqlite,Join,Sqlite,假设我有四个表、用户、联系人、文件和用户文件 用户可以上传文件并拥有联系人。他们可以选择与联系人共享上传的文件 当用户选择一个或多个上传的文件时,我想显示他们尚未与之共享所有选定文件的联系人列表。因此,如果他们选择了一个文件,它将显示尚未看到该文件的联系人。如果选择了多个文件,则会显示无法查看所有文件的联系人 现在,我正在使用sqlite3尝试这样的查询: select users.user_id, users.display_name from users, contacts, userfil

假设我有四个表、用户、联系人、文件和用户文件

用户可以上传文件并拥有联系人。他们可以选择与联系人共享上传的文件

当用户选择一个或多个上传的文件时,我想显示他们尚未与之共享所有选定文件的联系人列表。因此,如果他们选择了一个文件,它将显示尚未看到该文件的联系人。如果选择了多个文件,则会显示无法查看所有文件的联系人

现在,我正在使用sqlite3尝试这样的查询:

select users.user_id, users.display_name
from users, contacts, userfiles
where contacts.user_id = :user_id
and contacts.contact_id = users.user_id
and (
    userfiles.user_id != users.user_id
    and userfiles.file_id != :file_id
);
请注意,对于多个选定文件,最后一行是在循环中自动生成的

其中:user\u id是试图共享文件的用户,而:file\u id是文件,如果用户已经可以看到该文件,则会从结果中忽略它们。我最终得到的是一个联系人列表,这些联系人正在共享除所选联系人以外的任何文件,因此,如果用户正在与任何一个联系人共享多个文件,则该联系人会在列表中多次显示


我怎样才能避免重复?我只想检查文件是否已被共享,而不是获取不涉及特定文件的所有用户文件内容。

选择users.user\u id,users.display\u name 来自用户,联系人为c 其中c.user\u id=:user\u id c.contact\u id=users.user\u id 而且不存在 选择用户标识 从用户文件作为uf 其中uf.user\u id=c.contact\u id 和uf.file_id in:file_id ;

注意:文件id是所有文件id,用逗号分隔。不再循环运行多个查询

编辑:

这是我作为测试运行的数据:

create table users (user_id integer primary key, display_name text);
insert into users values (1,"bob");
insert into users values (2,"jim");
insert into users values (3,"bill");
insert into users values (4,"martin");
insert into users values (5,"carson");

create table contacts values (user_id integer, contact_id integer);
insert into contacts select u1.user_id, u2.user_id from users u1, users u2 where ui.user_id!=u2.user_id;

create table userfiles (user_id integer, file_id integer);
insert into userfiles values (1,10);
insert into userfiles values (2,10);
insert into userfiles values (3,10);
insert into userfiles values (4,10);
insert into userfiles values (1,20);
insert into userfiles values (2,30);
然后,如果我使用:user_id=5和:files_id=20,30运行查询,我会得到:

select users.user_id, users.display_name
from users, contacts as c
where c.user_id = 5
and c.contact_id = users.user_id
and not exists (
    select user_id
    from userfiles as uf
    where uf.user_id = c.contact_id
    and uf.file_id in (20,30)
);

UserID|Display_Name
3     |bill
4     |martin

据我所知,这似乎是您想要的,也就是说,唯一没有所有文件ID的用户。如果我误解了什么,请让我知道。

这似乎有效,不确定是否是最佳的,但这是我唯一能弄明白的方法:

select users.user_id, users.display_name
from users, contacts
where contacts.user_id = :user_id
and contacts.contact_id = users.user_id
and (
    select count(*)
    from userfiles
    where userfiles.user_id = users.user_id
    and userfiles.file_id in (:file_ids)
) < :number_of_files;

它选择所有联系人,但与所有文件ID匹配的联系人除外。它确实会选择与某些文件ID匹配的联系人,因为它会获取与指定ID匹配的联系人数,然后检查这是否少于提供的ID数。

@MPelletier实际上,这似乎不太有效,但比我更接近。如果我有多个文件ID,那么它将排除与其中任何一个匹配的所有联系人。我只想排除那些与它们都匹配的条款——我不确定我将如何做到这一点,而不可能在第一个条款中添加大量的and not exists条款。我可能需要将所有联系人放入dict,然后删除与所有文件ID匹配的联系人。@MPelletier明白了!查看我的答案:如果有什么不好的地方,请发表评论。我仍然在用SQLI来湿我的手。我运行了你的查询,并复制了你的结果,但不幸的是,在这种情况下,我想要的结果是让用户1、2、3和4出现。我只想排除已经可以看到所有选定文件的用户。在本例中,没有一个用户可以同时看到文件20和30,因此将显示所有文件。我选择了count*,因为是否显示用户取决于userfiles表中的几行,而不仅仅是其中一行是否存在。非常感谢你的帮助,它让我思考并帮助我解决了这个问题:哦,我确实让查询工作起来了,这是一个微妙的逃避问题哦,我明白了!然后是的,我认为您的查询是安全的,即使一个用户拥有的文件比其他人需要的多,我看到它被小心地限制在您想要的文件中。干得好!今晚我要测试一下。我的理解是,如果Bob共享了10000个文件,那么如果您选择他没有的几个文件,他将出现在该查询中。我想。。。你可以做的一件事就是接受我的查询或你原来的查询,并对其进行一些调整。使用循环遍历每个文件并执行大型交叉查询。你是对的,但这是我想要的行为:我只想排除已经可以查看每个选定文件的用户。无论如何,这是最糟糕的事情:这个查询在sqlite3解释器中工作,但在python中不工作。我搞不懂。啊,用Python我没用。请看我上面的编辑,我提供了一个测试数据样本,我用它来验证我认为正确的行为。