2014-05-07 28 views
0

有一個表likes是否可以在mysql中通過幾個不同的日期進行分組?

like_user_id | like_post_id | like_date 
---------------------------------------- 
1   | 2   | 1399274149 
5   | 2   | 1399271149 
.... 
1   | 3   | 1399270129 

我需要一個SELECT查詢,並通過分組根據時間1天,7天,1個月,1年計算爲特定like_post_id記錄。

的結果必須是這樣的:

period | total 
--------------- 
1_day | 2 
7_days | 31 
1_month | 87 
1 year | 141  

這可能嗎?

謝謝。

+0

您是否需要通過'like_user_id'或'like_post_id'對此進行聚合,或者只需要返回所有記錄的計數,就像您的示例輸出顯示的那樣? –

+0

什麼起點是決定的時間段?他們是否必須是行或者交叉表查詢是否適合您?這是一個用戶ID還是全部? –

+0

我需要通過'like_post_id'進行聚合。開始時間:從1年前到當前日期時間。 – Dmitry

回答

1

我對甲骨文語法創建的查詢,請根據您的分貝

select '1_Day' as period , count(*) as Total 
from likes 
where like_date>(sysdate-1) 
union 
select '7_days' , count(*) 
from likes 
where like_date>(sysdate-7) 
union 
select '1_month' , count(*) 
from likes 
where like_date>(sysdate-30) 
union 
select '1 year' , count(*) 
from likes 
where like_date>(sysdate-365) 

這裏想法是讓單期單次查詢,並應用在哪裏符合過濾條件的過濾器改變它。

1

此代碼顯示如何構建您可能需要的交叉表樣式查詢。這通過like_post_id進行聚合,您可能想要對其進行限制。此外,就上個月而言,我不知道您是指月至今,最近30天還是上個月,因此我已將這些留給了您。

SELECT 
like_post_id, 
-- cross-tab example, rinse and repeat as required 
-- aside of date logic, the SUM(CASE logic is designed to be ANSI compliant but you could use IF instead of CASE 
SUM(CASE WHEN FROM_UNIXTIME(like_date)>=DATE_SUB(CURRENT_DATE(), interval 1 day) THEN 1 ELSE 0 END) as 1_day, 
... 
FROM likes 
-- to restrict the number of rows considered 
WHERE FROM_UNIXTIME(like_date)>=DATE_SUB(CURRENT_DATE(), interval 1 year) 
GROUP BY like_post_id 
+0

謝謝!您和Vikas Hardia的解決方案適用於兩種不同的情況! – Dmitry

0

要靈活,簡單地做一個表time_intervals其持有秒from_length和to_length:

CREATE TABLE time_intervals 
( id int(11) not null auto_increment primary key, 
    name varchar(255), 
    from_seconds int, 
    to_seconds int 
); 

的選擇是那麼挺得筆直:

select like_post_id, ti.name as interval, count(*) as cnt_likes 
from time_intervals ti 
left /* or inner */ join likes on likes.like_post_id = 175 
    and likes.like_date between unix_timestamp(now()) - ti.to_seconds and unix_timestamp(now()) + ti.from_seconds 
group by ti.id 

隨着左連接你總是所有的時間間隔(即使有空洞),內部連接只有存在的時間間隔。

所以,你只改變表time_intervals,可以得到你想要的。 「175」代表你想要的帖子,當然如果你願意,你可以更改爲where ... in()

0

這是一個使用CROSS JOIN的替代方案。首先,使用TIMESTAMPDIFF函數和相應的參數(DAY/WEEK/MONTH/YEAR)計算時差。然後,如果計數等於1,則該值相加。最後,CROSS JOIN由包含句點名稱的內聯視圖組成。

SELECT 
    periods.period, 
    CASE periods.period 
    WHEN '1_day' THEN totals.1_day 
    WHEN '7_days' THEN totals.7_days 
    WHEN '1_month' THEN totals.1_month 
    WHEN '1_year' THEN totals.1_year 
    END total 
FROM 
(
SELECT 
    SUM(CASE days WHEN 2 THEN 1 ELSE 0 END) 1_day, 
    SUM(CASE weeks WHEN 1 THEN 1 ELSE 0 END) 7_days, 
    SUM(CASE months WHEN 1 THEN 1 ELSE 0 END) 1_month, 
    SUM(CASE years WHEN 1 THEN 1 ELSE 0 END) 1_year 
FROM 
(
SELECT 
     TIMESTAMPDIFF(YEAR, FROM_UNIXTIME(like_date), NOW()) years, 
     TIMESTAMPDIFF(MONTH, FROM_UNIXTIME(like_date), NOW()) months, 
     TIMESTAMPDIFF(WEEK, FROM_UNIXTIME(like_date), NOW()) weeks, 
     TIMESTAMPDIFF(DAY, FROM_UNIXTIME(like_date), NOW()) days 
FROM likes 
) counts 
) totals 
CROSS JOIN 
(
    SELECT 
    '1_day' period 
    UNION ALL 
    SELECT 
    '7_days' 
    UNION ALL 
    SELECT 
    '1_month' 
    UNION ALL 
    SELECT 
    '1_year' 
) periods 
相關問題