2016-05-15 55 views
2

我試圖將一個廣告的性能報告放在一起,顯示它在一天中的觀看次數和點擊次數。視圖和點擊被存儲在具有不同結構的單獨表格中,所以我認爲我必須執行聯合。兩個表上的MySQL聯盟,其中一個帶有時間戳,另一個帶有日期

我已閱讀並理解this fantastic piece。它幫助了我,但我認爲這是比這裏解釋的例子更復雜的一個層次。希望得到社區的幫助。

這是我的views表,它存儲廣告在一天中的觀看次數的計數器。

+-------------+--------------+ 
| COLUMN_NAME | COLUMN_TYPE | 
+-------------+--------------+ 
| ad_day_id | bigint(13) | 
| advert_id | bigint(20) | 
| date  | date   | 
| views  | mediumint(6) | 
+-------------+--------------+ 

這是我的clicks表,它存儲每個單獨的點擊。 (某些列排除在外,因爲他們不相關的問題)

+-------------+---------------------+ 
| COLUMN_NAME | COLUMN_TYPE   | 
+-------------+---------------------+ 
| id   | bigint(20) unsigned | 
| advert_id | bigint(20)   | 
| timestamp | timestamp   | 
+-------------+---------------------+ 

結果應該像(使用,只是爲了顯示格式沒有實數):

+------------+-------+--------+ 
| event_date | views | clicks | 
+------------+-------+--------+ 
| 2016-05-09 | 25 |  4 | 
| 2016-05-10 |  2 |  | 
| 2016-05-11 | 105 |  10 | 
| 2016-05-13 | 96 |  7 | 
| 2016-05-14 |  |  1 | 
+------------+-------+--------+ 

至於結果:

  • 不是每個日期都會有點擊或瀏覽
  • 有些日期可能有意見,不點擊
  • 有些日期可能有點擊和沒有意見

關的代碼......這就是我目前有:

SELECT 
    $views_table.date AS event_date, 
    $views_table.views, 
    '' AS clicks 
FROM 
    $views_table 
WHERE 
    ($views_table.date BETWEEN '$from_date' AND '$to_date') 
    AND $views_table.advert_id=$advert_id 
UNION 
SELECT 
    CAST($clicks_table.timestamp AS DATE) AS event_date, 
    '' AS views, 
    COUNT($clicks_table.advert_id) AS clicks 
FROM 
    $clicks_table 
WHERE 
    (CAST($clicks_table.timestamp AS DATE) BETWEEN '$from_date' AND '$to_date') 
    AND $clicks_table.advert_id=$advert_id 
GROUP BY 
    event_date 
ORDER BY 
    event_date ASC; 

的一些注意事項上的代碼:

  • 這些點擊單獨存儲在時間戳上,因此必須是 轉換日期,然後按日期分組(或者至少這是我得到 有效結果的方式爲不同的報告)。
  • 該報告將以日期範圍爲特色,並針對特定廣告。這是解釋where子句。

在撰寫此問題時,我將代碼格式化得更好一些,而且爲了便於閱讀,我更改了解決最初問題的select語句的順序。顯然,兩個選擇都必須具有相同的列並且具有相同的順序。

我覺得我幾乎沒有,因爲這是我目前的結果是:

+------------+-------+--------+ 
| event_date | views | clicks | 
+------------+-------+--------+ 
| 2016-05-09 | 1  |  | 
| 2016-05-09 |  | 1  | 
| 2016-05-10 | 2  |  | 
| 2016-05-11 | 105 |  | 
| 2016-05-11 |  | 7  | 
| 2016-05-13 | 96 |  | 
| 2016-05-13 |  | 16  | 
| 2016-05-14 | 2  |  | 
| 2016-05-14 |  | 1  | 
| 2016-05-15 | 2  |  | 
| 2016-05-15 |  | 2  | 
+------------+-------+--------+ 

我剩下的問題是重複的日期。我該如何解決這個問題?
非常感謝那些善意回答的人!

+0

「我想我快到了」 - 你是。把你的代碼放在子查詢中,並使用'GROUP BY event_date'。您將需要調整SELECT。 –

回答

1

我修改您的查詢一點點(見在線評論),並把它包在一個子查詢在外部查詢使用GROUP BY event_date

SELECT event_date, MAX(views) AS views, MAX(clicks) AS clicks 
FROM (
    SELECT 
     views.date AS event_date, 
     views.views, 
     0 AS clicks -- '' causes strange results on sqlfiddle 
    FROM 
     views 
    WHERE 
     (views.date BETWEEN '2016-05-09' AND '2016-05-15') 
     AND views.advert_id=1 
    UNION 
    SELECT 
     CAST(clicks.timestamp AS DATE) AS event_date, 
     0 AS views, -- '' causes strange results on sqlfiddle 
     COUNT(clicks.advert_id) AS clicks 
    FROM 
     clicks 
    WHERE 
     (CAST(clicks.timestamp AS DATE) BETWEEN '2016-05-09' AND '2016-05-15') 
     AND clicks.advert_id=1 
    GROUP BY 
     event_date 
    -- ORDER BY is useless here 
) sub 
GROUP BY event_date 
ORDER BY event_date 

Demo

相反的CAST(clicks.timestamp AS DATE)你也可以使用DATE(clicks.timestamp)並希望MySQL將在未來使用索引。

+0

非常感謝保羅,這就像一個魅力,我用我的代碼中的所有建議去。 DATE()命令正常工作。嗚呼,很開心! – FreshSnow

1

這不是一個你需要的簡單聯合,而是一個聯合和連接。因此,您需要一個工會才能從視圖和點擊表中獲取日期的組合列表。然後,你需要離開加入viewes和點擊日期的名單表:

select ds.event_date, max(v.views) views, count(c.clicks) clicks 
from 
    (select distinct date as event_date from views 
    union distinct 
    select distinct date(timestamp) from clicks) ds 
left join views v on ds.event_date=v.date 
left join clicks c on ds.event_date=date(c.timestamp) 
where ... 
group by ds.event_date 
+0

你需要通過'advert_id'過濾你的子查詢。和(我不知道,但)不會'聯合不同'使'選擇不同'冗餘? –

+0

@PaulSpiegel我也不確定,因此我保留了選擇的區別。在第一個查詢中可能是多餘的。 – Shadow

+0

[文檔](http://dev.mysql.com/doc/refman/5.7/en/union.html)不是很精確:「重複的行從結果中刪除」。但我已經在[sqlfiddle](http://sqlfiddle.com/#!9/adbd9/7)上測試過。但是,如果'views.date'已經不是很明顯,那麼由於雙重連接,您將得到錯誤的點擊計數。但是,這是OPs問題:-) –

相關問題