2017-02-09 3 views
1

サンプル値を持つ4つのフィールドを有する「接続」テーブルから毎日受付比を計算しようとすると:で0受け入れ、1リクエストがあるためLEFTとacceptance_ratio計算JOINとSELF参加し、集約関数

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' 

01-05の場合、その日の受入れ率は0/1 = 0でなければなりません。同様に、01/06の比率は2/1でなければなりません。

しかし、各accept_linkには対応するrequest_linkがあります。ここで、request_linkのsender_id = accept_linkのrecipient_idです(またその逆もあります)。そこで、ここでは自己参加が必要です。私は、Joeが日付にかかわらずFrankの要求を受け入れることを確実にすると確信しています。

必須の結合条件を維持しながら集計が正しく機能するように、次の問合せをどのように修正できますか。 2つのWHERE条件が削除された場合、または必要な場合、クエリは正しく計算されますか?事前に

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

ありがとう:

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 

の予想される出力は次のようになります。

+0

カウントとは何ですか?リクエストリンクを持つ1人のユーザーと、受け入れリンクを持つ1人のユーザーですか?あなたの例では、フランク・ジョーとジョー・フランクの2つのレコードが4つあれば、どうなるでしょうか?この場合、二重カウントしたいですか? –

+0

はい、accept_linkカウントは、送信側からの対応するrequest_linkがある場合にのみ有効です。 簡単にするために、この例ではfrank-joeとjoe-frankのレコードが2つしかないとしましょうが、ここで言及しましたが、クエリー内の複数のレコードをどのように考慮するべきか分かります。 –

+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

もう一度、ここで自己結合を使用する必要はないと思います。代わりに、単にテーブル全体にわたり、条件付き集約を使用して、要求の数をカウントし、それぞれの日に起こった受け入れ:べき発生する可能性があり、私はゼロによる除算を処理するためのCASE式を使用することをここに

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 

注意、特定の日は要求しない。同じ招待状が複数回送信されないと私はここでも仮定します。

+0

ありがとう、ティム、これは大いに役立ちます。 sender_idとrecipient_idの要件が満たされていることを確認する方法はありますか?たとえば、JoeがFrankの要求を受け入れるとしますが、データベースのFrankのrequest_linkエントリが 'Jo'に誤っているとします。その場合、request_linkもaccept_linkもカウントしないでください。 idsがSUMに含まれる前に予想どおりに一致することを確認する方法はありますか? –

+0

@SidneyCarton私はあなたにアップデートを与えました。私はローカルでテストしたところ、動作しているようです。 –

+0

ありがとう、Tim –

関連する問題