Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用activerecord发出请求,仅从组中获取用户,而不从其他组中获取用户_Sql_Ruby On Rails_Ruby On Rails 4_Rails Activerecord - Fatal编程技术网

Sql 使用activerecord发出请求,仅从组中获取用户,而不从其他组中获取用户

Sql 使用activerecord发出请求,仅从组中获取用户,而不从其他组中获取用户,sql,ruby-on-rails,ruby-on-rails-4,rails-activerecord,Sql,Ruby On Rails,Ruby On Rails 4,Rails Activerecord,我试图从几个具有给定ID的组中获取用户,并从其他组中排除这些用户 我试过这样的方法: User.joins(:groups).where(groups: {id: ["8939","8950"]}).where.not(groups: {id: 8942}).map(&:id) User Load (0.9ms) SELECT "users".* FROM "users" INNER JOIN "groups_users" ON "groups_users"."user_id" =

我试图从几个具有给定ID的组中获取用户,并从其他组中排除这些用户

我试过这样的方法:

User.joins(:groups).where(groups: {id: ["8939","8950"]}).where.not(groups: {id: 8942}).map(&:id)
  User Load (0.9ms)  SELECT "users".* FROM "users" INNER JOIN "groups_users" ON "groups_users"."user_id" = "users"."id" INNER JOIN "groups" ON "groups"."id" = "groups_users"."group_id" WHERE "groups"."id" IN (8939, 8950) AND "groups"."id" != $1  [["id", 8942]]
=> [119491, 119489, 119490, 119492, 119488, 119484, 119483, 119491, 119482]
但这是不对的

组8942中的用户


where.not在user groups.id上不起作用!=$1[[id,8942]]。为什么?

正确的方法是使用SQL条件。我希望有一个特定的ActiveRecord助手方法来实现这一点,但目前还没有

好的,使用纯SQL很好:

User.where("EXISTS (SELECT 1 FROM groups_users WHERE groups_users.user_id = users.id AND groups_users.group_id IN (?))", [8939, 8950]).
  where("NOT EXISTS (SELECT 1 FROM groups_users WHERE groups_users.user_id = users.id AND groups_users.group_id IN (?))", [8942])
您对原始查询所做的是要求不要将ID为[8942]的组加入查询,而只加入ID为[89398950]的组。好吧,你现在可以看到这没有任何意义:这就像要求选择每个名为bob而不是charlie的用户。第二个条件不会给第一个条件添加任何内容

联接查询是对列进行乘法运算,因此,如果用户在每个组中,则结果集为:

user_id | group_id
1       | 8939
1       | 8950
1       | 8942
然后过滤掉后一行:1 | 8942。用户1仍然在结果集中并返回

要让数据库只返回不与另一个关系连接的记录,您应该显式地使用NOT EXISTS,它显式地用于此目的:

现在有一个gem可以使用。全面披露:我最近创造了那块宝石

有了它,您可以完成您的任务,简单到:

User.where_exists(:groups, id: [1, 2]).where_not_exists(:groups, id: [3, 4])

再次感谢EugZol。你不是我的支持者。我肯定需要了解更多的sql请求。你给我的那个我有一个小错误。PG::UndefinedTable:错误:缺少表组用户的子句条目第1行:…存在的用户从组使用的组中选择1…哈哈,我真的是一个存在的?支持人员:团队使用的地方——是你的打字错误,把它改成一个。groups.user_id.PG::UnfinedColumn:错误:column groups.user_id不存在第1行:…存在的用户从组所在的组中选择1。使用。。。用你的version@eirikir它不允许做我在这里做的事情,我经常面临这样的任务——用存在的连接条件进行查询。好的,可以编写GroupUser.where'group_id IN',[1,2,3]。where'user_id=users.id'。到sql而不是内部sql,但它没有真正的帮助。@BeniMio这是一种无效的方法,因为它会用Ruby代码减去记录,而不是在数据库内部。因此,来回传输大约两倍的数据会浪费时间,而且会损失CPU/RAM,因为Ruby在计算方面不如用C编写并针对任务进行优化的数据库引擎有效。在正常情况下,您希望将这些事情委托给DB引擎。
User.where_exists(:groups, id: [1, 2]).where_not_exists(:groups, id: [3, 4])