2012-08-09 69 views
2

我已經爲個人信息如下表:如何從MySQL表查詢複雜的布爾條件

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到其他所有收件人。)

或從發件人的發件箱

  1. 如果所有接收者已經從他們的收件箱(del_by_rec = 1該消息的所有接收者)中刪除該消息。

否則,當前用戶將只需設置標誌這條消息刪除了相應的del_by_recdel_by_send標誌爲1

有沒有辦法有效地查詢這個標準

  1. 查看當前消息的當前用戶;或
  2. 當前用戶批量刪除多個郵件(我想這種情況下多行結果將被返回)。

返回布爾值/整數將會很棒。

對我的愛,我無法擺脫這種查詢(假定用戶是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. 這對於多個消息id s來說是不合格的,以避免昂貴的foreach。我試着WHERE id IN (7,10)收件人burt,但我無法完成它的子查詢。

幫助。謝謝你們..

回答

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,只需更換「的ID組」與子查詢:

where id = @ID 

(@RECIPIENT和@ID的意思是,你想自定義查詢中的值)

+0

哇,你是一個傳奇!史詩般的感謝! :D我不得不在'group by id'之前添加'where id in(...)',而不是將它替換爲超過1條記錄。沒關係,對吧?再次,哇。 – 2012-08-09 17:20:04

+0

是的,添加一個where子句來選擇多個id很好。 – 2012-08-09 18:02:16

1

理念1:
反轉的布爾(撥打列類似保留或保存),更新用戶的刪除,然後再去做:

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

中的所有記錄與第二列中的0是可刪除的。

理念2:
你可以做2個步驟,用子查詢(可行的1號,但它可能是很多慢)
第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) 
) 

也許這些1可能給你所需要的思想或理念3火花;)

+0

非常感謝,克里斯托夫,將繼續關注它。< – 2012-08-09 11:43:08

0

什麼是有據可查的帖子...(我wiched他們都像你的。)...

我看到,每個消息只能有一個發送者...所以你爲什麼不把發送者的登錄信息和del_by_send標誌放在消息表中?

當發件人決定刪除郵件時,這將節省相當多的時間只更新一行。並通過記錄每個消息只發送一次發件人名稱很多空間...

這應該已經加快了速度,因爲您的表會更輕,並且更新永遠不會改變更多的一行。

(這將是更接近什麼是規範化的標準建議。檢查http://en.wikipedia.org/wiki/Database_normalization有關數據庫規範化的詳細信息)

簡化您的追求,安全缺失,我會在消息表中記錄的人數與消息有關。 (例如,對於消息ID 5,people_count將爲3(Tom,Josh和Chris)。每次用戶(發送者或接收者)刪除該消息時,將該計數器遞減。當計數器下降到0時,可以安全地刪除德消息。

希望這HEPS ...

+0

哈哈,謝謝,@ cptHammer。肯定會解決這個問題,我知道我是如何製作元表的......這是比薩和3小時的睡眠對人類的影響。大聲笑。讓我知道你是否更有智慧。謝謝 – 2012-08-09 12:19:36