2017-12-27 96 views
1

我有下列的表:SQL:在過去7天總條目,由天團,如果沒有那一天的條目設置爲0

id | time (SQL datetime) | url 

我需要爲過去7天總計從今天開始。

如果當天的總數爲0 - 將其返回爲0而不是完全不返回。

我已經試過這樣:

SELECT 
    time, COUNT(*) AS `num` 
FROM 
    entries 
WHERE 
    time > DATE_SUB(CURDATE(), INTERVAL 7 DAY) 
GROUP BY 
    time 

但它返回每小時彙總,從我的理解 - 我不知要日期時間戳轉換爲日期?

我還在學習SQL。

+0

*哪個* SQL? MS SQL Server? MySQL的? Postgres的?雖然像這樣一個簡單的問題可能是DBMS不可知的,但您仍應該標記您正在使用的DBMS。使用'CURDATE()'意味着MySQL,afaict。 –

回答

0

這是一個非常有趣的問題,因爲答案比問題複雜得多。

一般來說,SQL的設計目的不是像使用普通編程語言那樣使用循環和任意長度的列表,而是要動態地生成內容。它通常依賴於將表中所有的數據預先存在。

如果所有日期都在您現有的表中,沒問題,只需使用GROUP BY。但是在哪裏得到一個不存在於表中的日期,以顯示0計數?

看着SO,過去已經有幾個選項被討論和列出。

基本上這一切歸結爲4種選擇:

  • 使用臨時或永久表與日期的預建的必要範圍。與所有SQL服務器兼容,但有點不好意思,另外需要記住更新範圍表;
  • 在SQL以外的編程語言中創建所需日期的列表,然後比較返回的值。根本不算優雅;
  • 使用服務器端過程:便攜性較差,但比較容易 - 創建一個過程,該過程返回一個行列表,其中包含您指定爲過程參數的間隔中的日期行;
  • 使用額外的SQL服務器端的調整,如變量。

在你的情況,從這個問題的答案圖紙:Get a list of dates between two dates,我自己會考慮使用MySQL的變量,但是,因爲你需要包括日期,這不你的數據表中,這將可能不工作(至少我沒找到一個工作解決方案)。

所以,使用任何在上市問題的解決方案,您應該創建一些表像您的實際過去7天的日期列表,像這樣:

temporary table LASTDAYS 
datetime D 
------------- 
2017-12-27 
2017-12-26 
2017-12-25 
2017-12-24 
2017-12-23 
2017-12-22 
2017-12-21 

(順序不重要這裏)

然後你做:

SELECT DATE(LASTDAYS.D) AS D1, COUNT(YOURTABLE.id) AS num 
FROM LASTDAYS LEFT OUTER JOIN YOURTABLE 
ON DATE(YOURTABLE.time)=date(LASTDAYS.D) 
GROUP BY D1; 

(注OUTER join

創建這樣一個表會是這樣的最簡單的方法:

CREATE TEMPORARY TABLE LASTDAYS (D datetime); 

INSERT INTO LASTDAYS VALUES (CURRENT_TIMESTAMP); 
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 1 DAY)); 
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 2 DAY)); 
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 3 DAY)); 
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 4 DAY)); 
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 5 DAY)); 
INSERT INTO LASTDAYS VALUES (DATE_SUB(CURRENT_TIMESTAMP,INTERVAL 6 DAY)); 

然而,這確實是暴力破解。雖然,因爲你只需要這7行,它甚至可以包含在你的SELECT中。我不確定,但如果它被包含在BEGIN/END事務塊中,那麼臨時表甚至不會在SELECT之間持續存在。

相關問題