2015-02-24 62 views
2

我有一個名爲SQL鴻溝數據

表如下表:活動

userid appid type 
1   a  imp 
2   a  imp 
2   a  click 
3   a  imp 
4   a  imp 
4   a  click 
5   b  imp 
5   b  click 

我試圖計算出每個appid的點擊率。在這種情況下,我們將點擊率定義爲(點擊次數)/(展示次數)。我寫了下面的SQL:

SELECT appid, type, count(*) from activity group by appid, type 

,並得到了以下結果:

輸出:

appid type  count(*) 
a  click  2 
a  imp  4 
b  click  1 
b  imp  1 

下一步是做逐行師。最終,我想實現以下目標:

目標:

appid click-through 
a  .5      # 2/4 = .5 
b  1       # 1/1 = 1 

這是如何實現的呢?理想情況下,我希望這可以在一個查詢中完成,那有可能嗎?

回答

3

可以使用條件聚集做到這一點:

select appid 
     , SUM(CASE WHEN type = 'click' THEN 1 END)*1.0 
     /SUM(CASE WHEN type = 'imp' THEN 1 END) AS click_through 
    from activity 
    group by appid 

演示:SQL Fiddle

如果使用MySQL,可以進一步簡化爲:

select appid 
     , SUM(type = 'click')*1.0 
     /SUM(type = 'imp') AS click_through 
    from activity 
    group by appid 
+0

對於這個例子,它工作正常,但現在想象你有沒有印象的點擊,你想刪除它們,因爲這很可能是錯誤。這個查詢會忽略它。 – zipp 2017-03-31 17:59:42

+0

@zipp當然可以調整條件來處理額外的複雜性,例如,可以將整個事件包裝在一個「CASE」表達式中,該表達式用於檢查以確保展示次數高於點擊次數。 – 2017-03-31 20:13:45

+0

我打開了一個單獨的問題,以防萬一您面臨挑戰: http:// stackoverflow。COM /問題/ 43148974/MySQL的,有條件自加盟 – zipp 2017-03-31 20:14:53

2

只是算子查詢中的曝光和點擊,並加入他們一起:

select appid, 
num_impressions, 
num_clicks, 
cast(num_clicks as float)/num_impressions as ctr 
from(
    select appid, count(1) as num_impressions 
    from activity 
    where type = 'imp' 
    group by appid 
)a 
join(
    select appid, count(1) as num_clicks 
    from activity 
    where type = 'click' 
    group by appid 
)b 
on (a.appid = b.appid); 

注意在ctrnum_clicks類型轉換,以避免整數除法。

+1

我喜歡這是多麼明確,它非常優雅。 – invoker 2015-02-24 18:50:06

+0

@harrisried:謝謝。 :)如果您發現答案有幫助,請考慮提供答案和/或接受答案(通過點擊投票箭頭下方左上角的複選標記)。 – 2015-02-24 19:01:52

+0

@harrisried:謝謝你的接受。我修正了一些小問題('ctr = clicks/impressions',而不是其他方法)。另外,您可能需要考慮將'join'轉換爲'left join',並將'cast(num_clicks as float)'替換爲'cast(合併(num_clicks,0)爲float)'來計算具有展示次數的應用沒有點擊(如果這適用於您的數據)。 – 2015-02-24 19:11:49

1

因爲你是用兩種不同的骨料使用不同的標準處理,您可以用子查詢做到這一點:

SELECT d1.appid, (
    SELECT count(*) 
    FROM activity d2 
    WHERE d2.appid = d1.appid 
     d2.type = 'click' 
)/(
    SELECT count(*) 
    FROM activity d3 
    WHERE d3.appid = d1.appid 
     d3.type = 'imp' 
) AS click_through 
FROM activity d1; 
0
CREATE TABLE #activity 
(
    userid INT , 
    appid VARCHAR(1), 
    [type] VARCHAR(5) 
) 

INSERT INTO #activity 
VALUES 
(1,   'a' ,  'imp'), 
(2,   'a',  'imp'), 
(2,   'a',  'click'), 
(3,   'a',  'imp'), 
(4,   'a',  'imp'), 
(4,   'a',  'click'), 
(5,   'b',  'imp'), 
(5,   'b',  'click') 


SELECT A.appid, CAST(a.Clicks AS FLOAT)/B.Imp 
FROM 
( SELECT appid, COUNT(1) Clicks 
    FROM #activity 
    WHERE [type] ='CLICK' 
    GROUP BY appid 
) A 
INNER JOIN 
( SELECT appid, COUNT(1) Imp 
    FROM #activity 
    WHERE [type] ='imp' 
    GROUP BY appid 
) B ON A.appid = B.appid 

DROP TABLE #activity