2017-02-09 103 views
1

試圖從「連接」表,其具有4個字段與樣本值計算每日接受比率:計算acceptance_ratio與LEFT JOIN和SELF JOIN和聚合函數

date   action   sender_id  recipient_id 
'2017-01-05', 'request_link', 'frank', 'joe' 
'2017-01-06', 'request_link', 'sally', 'ann' 
'2017-01-07', 'request_link', 'bill', 'ted' 
'2017-01-07', 'accept_link', 'joe', 'frank' 
'2017-01-06', 'accept_link', 'ann', 'sally' 
'2017-01-06', 'accept_link', 'ted', 'bill' 

因爲有0接受和1個請求上01-05,其日常接受率應爲0/1 = 0。同樣,01-06的比例應爲2/1,01-07應爲1/1。

但是,每個accept_link都有一個相應的request_link,其中request_link的sender_id = accept_link的recipient_id(反之亦然)。所以在這裏需要自聯接,我相信可以確保Joe接受Frank的請求,無論日期如何。

如何糾正下面的查詢,以便在保留所需的連接條件的情況下正確工作?如果兩個WHERE條件被刪除,查詢是否能夠正確計算?還是它們是必需的?

SELECT f1.date, 
    SUM(CASE WHEN f2.action = 'accept_link' THEN 1 ELSE 0 END)/
    SUM(CASE WHEN f2.action = 'request_link' THEN 1 ELSE 0 END) AS acceptance_ratio 
FROM connecting f1 
LEFT JOIN connecting f2 
ON f1.sender_id = f2.recipient_id 
LEFT JOIN connecting f2 
ON f1.recipient_id = f2.sender_id 
WHERE f1.action = 'request_link' 
AND f2.action = 'accept_link' 
GROUP BY f1.date 
ORDER BY f1.date ASC 

預期的輸出應該是這個樣子:

date   acceptance_ratio 
'2017-01-05' 0.0000 
'2017-01-06' 2.0000 
'2017-01-07' 1.0000 

在此先感謝。

+0

什麼構成一個計數?它是一個人與一個請求鏈接,另一個與一個接受鏈接?在你的例子中,如果我們有四條記錄會發生什麼事情,兩個是弗蘭克喬,兩個是喬弗蘭克?你想在這種情況下加倍計數? –

+0

是的,只有在發件人有相應的request_link時,accept_link數才應該有效。 爲了簡單起見,我們假設在這個例子中,frank-joe和joe-frank只有兩條記錄,儘管現在你提到它了,但我很好奇你會怎麼解釋查詢中的多條記錄。 –

+1

請參閱http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-sql-查詢 – Strawberry

回答

1

再次,我不認爲你需要在這裏使用自我加入。所以,應該使用條件聚集在整個表格,並計算請求的數量,並接受其發生在每一天:

SELECT t.date, 
     CASE WHEN t.num_requests = 0 
      THEN 'No requests available' 
      ELSE CAST(t.num_accepts/t.num_requests AS CHAR(50)) 
     END AS acceptance_ratio 
FROM 
(
    SELECT c1.date, 
      SUM(CASE WHEN c1.action = 'accept_link' AND c2.action IS NOT NULL 
        THEN 1 ELSE 0 END) AS num_accepts, 
      SUM(CASE WHEN c1.action = 'request_link' THEN 1 ELSE 0 END) AS num_requests 
    FROM connecting c1 
    LEFT JOIN connecting c2 
     ON c1.action  = 'accept_link' AND 
      c2.action  = 'request_link' AND 
      c1.sender_id = c2.recipient_id AND 
      c2.recipient_id = c1.sender_id 
    GROUP BY c1.date 
) t 
ORDER BY t.date 

注意這裏我用一個CASE表達零來處理鴻溝,可能發生應某一天沒有要求。我也在這裏假設相同的邀請不會被髮送超過一次。

+0

謝謝,蒂姆,這有助於很多。有沒有辦法確保滿足sender_id和recipient_id要求?例如,讓我們說Joe接受Frank的請求,但是也許Frank的數據庫中的request_link條目被錯誤地記錄爲'Jo',在這種情況下,request_link和accept_link都不應該被計入。有沒有辦法在將它們包含在SUM中之前驗證ID是否符合預期? –

+0

@SidneyCarton我給你一個更新,我在本地測試,它似乎工作。 –

+0

非常感謝Tim –