如何从MySQL表中查询复杂的布尔条件

时间:2012-08-09 11:10:56

标签: mysql boolean conditional-statements

我有个人信息的下表:

id*    sender*    recipient* del_by_rec del_by_send
-+----------+-------------+-----------+-----------+
 2     tom        beth            0          1
 5     tom        josh            0          1
 5     tom        chris           1          1
 7     ashley     burt            1          0
 8     jenna      tom             1          0
 8     jenna      ashley          0          0
 8     jenna      jenna           1          0
10     ashley     burt            0          0

,其中

  • id是消息ID,
  • senderrecipient是用户登录,
  • sender对邮件id
  • 而言是唯一的
  • 消息recipient
  • 可以有多个id 如果收件人已从收件箱中删除了,则
  • del_by_rec为1 如果发件人从发件箱中删除了邮件,则
  • del_by_send为1。
  • id - sender - recipient是主键,
  • id引用包含该消息的另一个表中的主键id

一旦当前用户决定这样做,我需要确定是否可以从表中删除

来自收件人收件箱的

  1. 如果发件人已从其发件箱中删除了该邮件(del_by_send = 1);和
  2. 如果此用户是尚未从其收件箱中删除此邮件的唯一收件人(此del_by_rec = 0,则此del_by_rec = 1,而所有其他收件人都为del_by_rec = 1。)
  3. 或来自发件人的发件箱

    1. 如果所有收件人都已从收件箱中删除此邮件(此邮件的所有收件人都为del_by_rec = 1)。
    2. 否则,当前用户只会通过将相应的del_by_sendashley标记设置为1来标记此消息以进行删除。

      有没有办法有效地查询

      的此条件
      1. 当前用户查看当前消息;或
      2. 当前用户质量删除多条消息(我想在这种情况下会返回多行结果)。
      3. 返回boolean / int会很棒。

        为了爱我,我无法通过此查询(假设用户为8且她想从收件箱中删除邮件SELECT ( (SUM(del_by_send) > 0) # sender has deleted (at least 1) && ((SUM(del_by_rec) + 1) >= COUNT(id)) # only 1 recipient has not deleted yet && ((SELECT del_by_rec FROM msg_meta WHERE recipient = 'ashley' AND id = 8) = 0) # and that recipient is this user ) FROM msg_meta WHERE id = 8 GROUP BY id ):

        id
        1. 这似乎可以胜任这项工作,但它有点矫枉过正吗?
        2. 多条消息foreach无法避免昂贵的WHERE id IN (7,10)。我为收件人burt尝试了{{1}},但我无法将其用于子查询..
        3. 帮助。谢谢你们..

3 个答案:

答案 0 :(得分:1)

想法1:
反转布尔值(将列称为保留或保存),首先更新用户的删除然后执行:

SELECT id , SUM(del_by_send) + SUM(del_by_rec)
FROM msg_meta
WHERE id = 8
GROUP BY id

第二列中0为0的所有记录都是可删除的。

创意2:
您可以通过两个步骤和一个子查询完成它(可用于1个id,但它可能很慢) 步骤1:更新1或多个消息ID的删除标记(通过rec或发送) 第2步:

SELECT id 
FROM msg_meta t
WHERE t.id = 8
AND NOT EXISTS(
  SELECT id
  FROM msg_meta t2
  WHERE t.id = t2.id
  AND (t2.del_by_rec = 0 OR t2.del_by_sent = 0)
)

也许其中一个可能会给你你需要的想法或想法3的火花;)

答案 1 :(得分:1)

我的建议是使用子查询在消息级别获取所需的信息,然后将逻辑应用于此。以下查询结束:

select id, (case when sum_del_by_send > 0 and (num_rec - sum_del_by_rec) <= 1
                 then 'Y'
                 else 'N'
            end) as IsSafeToDelete
from (select id,
             sum(del_by_send) as sum_del_by_send,
             sum(del_by_rec) as sum_del_by_rec,
             count(*) as num_rec
      from msg_meta
      group by id
     ) m

这不会考虑当前的收件人。这个变体确实:

select id, (case when sum_del_by_send > 0 and (num_others - sum_del_by_others) = 1
                 then 'Y'
                 else 'N'
            end) as IsSafeToDelete
from (select id,
             sum(del_by_send) as sum_del_by_send,
             sum(case when recipient <> @RECIPIENT then del_by_rec end) as sum_del_by_others,
             sum(case when recipient <> @RECIPIENT then 1 else 0 end) as num_others,
             count(*) as num_rec
      from msg_meta
      group by id
     ) m

一次处理所有邮件。要处理特定的消息ID,只需将子查询中的“group by id”替换为:

where id = @ID

(@ RECIPIENT和@ID是您要为其自定义查询的值。)

答案 2 :(得分:0)

这篇文章记录得很好...(我觉得他们都像你的一样。)......

我看到每封邮件只能有一个发件人...那你为什么不把发件人的登录信息和del_by_send标志放在邮件表中呢?

当发件人决定删除邮件时,这将节省相当多的时间只更新一行。通过仅记录每条消息的发件人姓名来节省大量空间......

这应该已经加快了速度,因为你的表会更轻,而且更新永远不会改变多一行。

(这将更接近标准化标准的建议。检查http://en.wikipedia.org/wiki/Database_normalization以获取有关数据库规范化的更多信息)

为了简化您的安全删除任务,我会在消息表中记录与消息有关的人数。 (例如,对于消息ID 5,people_count将为3(Tom,Josh和Chris)。每次用户(发送者或接收者)删除该消息时,递减此计数器。当计数器降至0时,可以安全删除de message。

希望这会好起来......