2

我有下表用于个人消息:

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,
  • sender并且recipient是用户登录,
  • sender对消息是唯一的id
  • recipient一条消息可以有多个id
  • del_by_rec如果邮件已被收件人从其收件箱中删除,则为 1,并且
  • del_by_send如果邮件已被发件人从他的发件箱中删除,则为 1。
  • id- sender-recipient是主键,并且
  • idid引用包含该消息的另一个表中的主键。

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

从收件人的收件箱

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

或从发件人的发件箱

  1. 如果所有收件人都已从其收件箱中删除了此邮件(del_by_rec= 1 表示此邮件的所有收件人)。

否则,当前用户将通过将其对应的del_by_recordel_by_send标志设置为 1 来标记此消息以进行删除。

有没有办法有效地查询这个标准

  1. 当前用户查看当前消息;或者
  2. 当前用户大量删除多条消息(我正在考虑在这种情况下返回多行结果)。

返回一个 boolean/int 会很棒。

为了我的爱,我无法通过这个查询(假设用户是ashley并且她想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
  1. 这似乎完成了这项工作,但它有点矫枉过正吗?
  2. 对于多个 messageid避免昂贵的foreach. 我尝试WHERE id IN (7,10)了收件人burt,但我无法将其完全用于子查询..

帮助。谢谢大家。。

4

3 回答 3

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 是您要自定义查询的值。)

于 2012-08-09T14:07:53.823 回答
1

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

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

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

想法 2:
您可以分两步使用子查询(对于 1 个 id 可行,但可能会很慢)
第 1 步:更新删除标志(通过 rec 或通过发送)为 1 个或多个消息ID。
第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 的火花;)

于 2012-08-09T11:36:01.523 回答
0

What a well documented post... (I wiched they were all like yours.)...

I see that there can only be one sender per message... so why wouldn't you put the sender's login, and the del_by_send flag in the messages table ?

This will save quite a lot of time updating only one row when the sender decide to delete the message. and a lot of space by recording only once the sender name for each message...

This should already speed things up because your tables will be lighter, and the updates never change more then one row.

(this would be closer to what is recommended by normalisation standards. Check http://en.wikipedia.org/wiki/Database_normalization for more info on database normalization)

to simplify your quest to safe-deletion, I would record in the message table the number of people involved with the message. (say, for message ID 5, people_count would be 3 (Tom, Josh and Chris). Each time a user (sender or receiver) deletes the message, decrement this counter. When the counter is down to 0, it is safe to delete de message.

Hope this heps...

于 2012-08-09T12:06:10.773 回答