SQL自引用查询

时间:2015-06-19 02:36:20

标签: sql activerecord

我有一个包含四个表的模式用户,组,成员资格和MembershipControls

会员资格是用户与用户之间的M:M。基团。

成员资格控制指定用户必须已经成为其成员的组。

例如,成为" Green"的成员。用户组必须已经是" Blue"的成员。或者"黄色"基团。

当用户是" Green"的成员时他们的成员资格取决于他们是" Blue"或者"黄色"组。如果用户不再是" Blue"如果他们不再是"黄色"的成员,他们现有的会员资格仍然存在。然后他们的"" Green"应删除。

我正在尝试找出将从会员资格中删除会员控制的记录中删除的sql。

http://sqlfiddle.com/#!9/302d2

基于上述小提琴,以下会员资格有效: (1,1,1) (2,1,2) (3,1,3) (4,1,4)

如果中间两个会员资格高于绿色&蓝色被删除唯一有效的会员资格将是: (1,1,1)

即。如果Memberships表包含: (1,1,1) (1,1,4) 最后一条记录无效,应删除,因为它违反了MembershipControls。

这是因为会员控制指定成为群组成员:4您还需要成为群组成员:2或群组:3

4 个答案:

答案 0 :(得分:1)

尝试:

delete from memberships
where user_id in
  (
    select    user_id
    from      memberships
    group by  user_id
    having    sum(case when group_id = 4 then 1 else 0 end) = 1
          and sum(case when group_id = 2 then 1 else 0 end) = 0
          and sum(case when group_id = 3 then 1 else 0 end) = 0
  )
  and group_id = 4

简单地说,这会从成员资格表中删除用户属于第4组的所有行,但不会删除第2组或第3组(而只有第4组的行)。

答案 1 :(得分:0)

我相信你要做的是:

Select * From Memberships
Where ((group_id = 1) OR (group_id = 2))
AND
user_id = 1

然后将这些user_id转换为成员资格控制。这样就可以删除剩余的记录。

我不太清楚MySQL语法并且SQL Fiddle在我身上崩溃所以我无法测试它。我确实发现这篇文章很有帮助:http://www.techonthenet.com/mysql/and_or.php

基本上如何在Where语句中使用AND / OR。如果这有帮助,请告诉我。 :)

答案 2 :(得分:0)

这是一个假设唯一有效的会员颜色组合是绿 - 蓝和绿 - 黄的查询。这分别对应于group_id 分别为6和7。在我的查询中,我计算每个用户的组成员资格总和,并将JOIN结果返回Membership表。然后我删除任何没有有效group_id总和的记录。

DELETE
FROM Memberships m
INNER JOIN
(
    SELECT user_id, SUM(group_id) AS group_sum
    FROM Memberships
    GROUP BY user_id
) m2
ON m.user_id = m2.user_id
WHERE m2.group_sum != 6 OR m2.group_sum != 7

如果整套允许或不允许的颜色具有唯一的总和,则此方法应该没有问题。我也假设你不需要触发器,正如@BrianDeMilia指出的那样。

答案 3 :(得分:0)

子查询标识用户有权成为其成员的组,父查询标识用户当前所属的组。

当针对上面的小提琴运行此查询时,它不会标识从成员资格中删除的记录。如果从成员资格表(2,1,2)中删除中间的两行& (3,1,3)然后查询从成员资格中标识一行以进行删除。

SELECT Memberships.*
FROM Memberships
INNER JOIN MembershipControls ON Memberships.group_id = MembershipControls.group_id
WHERE Memberships.user_id = 1
AND Memberships.group_id NOT IN
(
  SELECT MembershipControls.group_id
  FROM GROUPS
  INNER JOIN Memberships ON Groups.id = Memberships.group_id
  INNER JOIN MembershipControls ON Memberships.group_id = MembershipControls.criteria_id
  WHERE Memberships.user_id = 1
  GROUP BY MembershipControls.group_id
)