1. 程式人生 > 資料庫 >SQL程式設計:異常的郵件概率

SQL程式設計:異常的郵件概率

題目描述

現在有一個需求,讓你統計正常使用者傳送給正常使用者郵件失敗的概率:
有一個郵件(email)表,id為主鍵, type是列舉型別,列舉成員為(completed,no_completed),completed代表郵件傳送是成功的,no_completed代表郵件是傳送失敗的。簡況如下:

第1行表示為id為2的使用者在2020-01-11成功傳送了一封郵件給了id為3的使用者;
...
第3行表示為id為1的使用者在2020-01-11沒有成功傳送一封郵件給了id為4的使用者;
...
第6行表示為id為4的使用者在2020-01-12成功傳送了一封郵件給了id為1的使用者;
下面是一個使用者(user)表,id為主鍵,is_blacklist為0代表為正常使用者,is_blacklist為1代表為黑名單使用者,簡況如下:


第1行表示id為1的是正常使用者;
第2行表示id為2的不是正常使用者,是黑名單使用者,如果傳送大量郵件或者出現各種情況就會容易傳送郵件失敗的使用者
。。。
第4行表示id為4的是正常使用者
現在讓你寫一個sql查詢,每一個日期裡面,正常使用者傳送給正常使用者郵件失敗的概率是多少,結果保留到小數點後面3位(3位之後的四捨五入),並且按照日期升序排序,上面例子查詢結果如下:

結果表示:

2020-01-11失敗的概率為0.500,因為email的第1條資料,傳送的使用者id為2是黑名單使用者,所以不計入統計,正常使用者發正常使用者總共2次,但是失敗了1次,所以概率是0.500;

2020-01-12沒有失敗的情況,所以概率為0.000.

(注意: sqlite 1/2得到的不是0.5,得到的是0,只有1*1.0/2才會得到0.5,sqlite四捨五入的函式為round)

思路:首先我們需要按照題目要求找到正常使用者(即is_blacklist=0的使用者),這需要我們將兩個表聯結起來並排除掉黑名單:

select xxx 
from email
join user as u1 on (email.send_id=u1.id and u1.is_blacklist=0)
join user as u2 on (email.receive_id=u2.id and u2.is_blacklist=0)

之後我們可以首先按照date進行分組,之後藉助case語句查詢completed的使用者,並通過概率計算公式進行計算,本題完整程式碼如下:

select
a.date as date,
round(
    sum(case a.type when 'completed' then 0 else 1 end)*1.0/count(a.type),3
) as p
from 
email as a
join user as u1 on (a.send_id=u1.id and u1.is_blacklist=0)
join user as u2 on (a.receive_id=u2.id and u2.is_blacklist=0)
group by
a.date
order by
a.date;