2017-07-27 50 views
-1

我想查找最受歡迎的值並按月排列結果。 我的意思是,按月出現的價值最高。SQL如何找到最熱門的按月排序

我做了大量的研究和一些答案,以找到最受歡迎的產品。通常情況下,該解決方案是一組由治安與限位1 像這樣:Find most frequent value in SQL column


這裏是我的示例表。 讓我們試着找出每個人最喜歡的顏色。

表picked_colors

| Color | Name | Month | 
|--------|------|-------| 
| Yellow | Tom | 04 | 
| Red | Tom | 04 | 
| Yellow | Tom | 04 | 
| Blue | Tom | 03 | 
| Red | Sam | 04 | 
| Pink | Sam | 04 | 
| Pink | Sam | 04 | 
| Yellow | Sam | 03 | 

如此看來,4月份,湯姆首選黃色(他把它撿了兩次VS一次紅色的),並且他喜歡在三月的藍色。 Sam最喜歡的一個是四月份的粉紅色,三月份是黃色。

所以我想返回 一個表,其中名稱=湯姆

月/彩色
04 /黃
03 /藍

,並在那裏名稱=山姆

月份/顏色
04 /粉色
03 /黃


我想出頭真的不喜歡的工作,例如這個,我可以找到湯姆多少次,每月每個喜歡的顏色。有了這個,我可以選擇的最大值作爲最喜歡的一個,但我不知道如何:

SELECT MONTH(month), color, COUNT(color) 
FROM picked_colors 
WHERE name = 'Tom' 
GROUP BY color, MONTH(month) 
ORDER BY MONTH(month) desc; 

返回:

月/顏色/計數
04 /黃色/ 2
04 /紅/ 1
03/blue/1

其實它正是我所需要的,除了第二行我不想要。 我想到了max(count()),但它不被mysql允許。

有人嗎? 非常感謝。

+0

向我們展示了 「很多東西」,你試過。我們需要知道您目前如何嘗試解決這個問題,因爲您很可能已經擁有大部分解決方案。 – user2366842

+0

如果最喜歡的項目有領帶,你想要什麼樣的結果? –

+0

@ user2366842我試圖讓它更清楚。你可以嗎? – Cyril

回答

0

此代碼有效。

因爲您可能會有重複,並且您只需要爲每個用戶/月份組合提供一個答案,所以我們必須通過解決方案獲得更高級的解決方案。

該解決方案首先根據我們關心的每個組合(aggregated_picked_colors子查詢)有多少行進行聚合,然後爲每個我們關心的組合(sorted_picked_colors子查詢)分配顏色數量的排名。頂級查詢然後只是從ranking_picked_colors中提取排名最高的解決方案。

上增加這些排名列計數器的方法的更多細節,請訪問:ROW_NUMBER() in MySQL

/* 
create table picked_colors (
    color varchar(10), 
    name varchar(10), 
    month tinyint 
); 

insert into picked_colors (color, name, month) values ('Yellow', 'Tom', 4); 
insert into picked_colors (color, name, month) values ('Red', 'Tom', 4); 
insert into picked_colors (color, name, month) values ('Yellow', 'Tom', 4); 
insert into picked_colors (color, name, month) values ('Blue', 'Tom', 3); 
insert into picked_colors (color, name, month) values ('Red', 'Sam', 4); 
insert into picked_colors (color, name, month) values ('Pink', 'Sam', 4); 
insert into picked_colors (color, name, month) values ('Pink', 'Sam', 4); 
insert into picked_colors (color, name, month) values ('Yellow', 'Sam', 3); 
*/ 

select 
    name, month, color 
from 
    (
    select 
     @row_num := IF(@prev_value=concat_ws('', name, month),@row_num+1,1) as row_number, 
     color, name, month, row_count, 
     @prev_value := concat_ws('', name, month) as prev_value 
    from 
     (
     select 
      name, month, color, count(*) as row_count 
     from 
      picked_colors 
     group by 
      name, month, color 
    ) aggregated_picked_colors, 
     (select @row_num := 1) x, 
     (select @prev_value := '') y 
    order by 
     name, month, row_count desc 
) ranked_picked_colors 
where 
    row_number = 1 
order by 
    name, month desc 

返回:

+------+-------+--------+ 
| name | month | color | 
+------+-------+--------+ 
| Sam |  4 | Pink | 
| Sam |  3 | Yellow | 
| Tom |  4 | Yellow | 
| Tom |  3 | Blue | 
+------+-------+--------+ 

編輯:添加說明/演練

的這裏的主要目標是我們想要獲取每組數據t我們正在彙總的帽子(在這種情況下,是每個名稱/月份的組合),並根據它們的行數對顏色進行排序。然後,我們要插入一個新列到這些結果與明確的排名,將顏色擁有最行,其顏色有下一個最行等

當我們開始,我們不是真的準備好排列這些事情,我們有多行說「黃色」,但我們希望數據顯示「黃色有5行」或沿着這些行。因此,我們寫的第一個查詢做這種聚合:

select 
    name, month, color, count(*) as row_count 
from 
    picked_colors 
group by 
    name, month, color; 

這將返回:

+------+-------+--------+-----------+ 
| name | month | color | row_count | 
+------+-------+--------+-----------+ 
| Sam |  3 | Yellow |   1 | 
| Sam |  4 | Pink |   2 | 
| Sam |  4 | Red |   1 | 
| Tom |  3 | Blue |   1 | 
| Tom |  4 | Red |   1 | 
| Tom |  4 | Yellow |   2 | 
+------+-------+--------+-----------+ 

這說明,每個名稱和月,每個顏色多少行了。

接下來,我們要證明,對於每個名稱和月,其顏色有最行,其顏色有第二個最行等,這邏輯是最令人費解。

的這裏的想法是,在表定義,我們插入這些行:

(select @row_num := 1) x, 
(select @prev_value := '') y 

這些命令基本上初始化這些變量。只提供X和Y名稱是因爲我們必須給這些「子查詢」一個名稱,它們實際上並未在任何地方使用。

內的查詢,我們使用這些變量。實際上,他們檢查顏色/名稱組合是否從前一行更改過。如果它們改變了,那麼我們將@row_num設置爲1,如果它們沒有改變,那麼我們就增加它。我們必須小心地按照與我們比較相鄰行相同的標準對此查詢進行排序;改變排序順序會破壞邏輯。

select 
    @row_num := IF(@prev_value=concat_ws('', name, month),@row_num+1,1) as row_number, 
    color, name, month, row_count, 
    @prev_value := concat_ws('', name, month) as prev_value 
from 
    (
    select 
     name, month, color, count(*) as row_count 
    from 
     picked_colors 
    group by 
     name, month, color 
) aggregated_picked_colors, 
    (select @row_num := 1) x, 
    (select @prev_value := '') y 
order by 
    name, month, row_count desc; 

這將返回:

+------------+--------+------+-------+-----------+------------+ 
| row_number | color | name | month | row_count | prev_value | 
+------------+--------+------+-------+-----------+------------+ 
|   1 | Yellow | Sam |  3 |   1 | Sam3  | 
|   1 | Pink | Sam |  4 |   2 | Sam4  | 
|   2 | Red | Sam |  4 |   1 | Sam4  | 
|   1 | Blue | Tom |  3 |   1 | Tom3  | 
|   1 | Yellow | Tom |  4 |   2 | Tom4  | 
|   2 | Red | Tom |  4 |   1 | Tom4  | 
+------------+--------+------+-------+-----------+------------+ 

這裏,我們可以忽略「prev_value」專欄中,我們實際上並不希望這些結果,我們只是設定要使用這個變量,當我們考察下一行。重要的是看看我們有相同的名稱和月份,row_count最高的顏色row_number = 1,row_count次高的顏色row_number = 2等。

最後一步是查詢只需要我們想要的字段,以及row_number = 1的行。這些行對應於每個名稱/月份組合的最高頻率顏色。

select 
    name, month, color 
from 
    (
    select 
     @row_num := IF(@prev_value=concat_ws('', name, month),@row_num+1,1) as row_number, 
     color, name, month, row_count, 
     @prev_value := concat_ws('', name, month) as prev_value 
    from 
     (
     select 
      name, month, color, count(*) as row_count 
     from 
      picked_colors 
     group by 
      name, month, color 
    ) aggregated_picked_colors, 
     (select @row_num := 1) x, 
     (select @prev_value := '') y 
    order by 
     name, month, row_count desc 
) ranked_picked_colors 
where 
    row_number = 1 
order by 
    name, month desc 

這將返回:

+------+-------+--------+ 
| name | month | color | 
+------+-------+--------+ 
| Sam |  4 | Pink | 
| Sam |  3 | Yellow | 
| Tom |  4 | Yellow | 
| Tom |  3 | Blue | 
+------+-------+--------+ 
+0

非常感謝。你能解釋一下代碼嗎?這是相當先進的,我無法理解它的一切。 – Cyril

+0

我會在幾個小時內寫出詳細的演練,也許是在一天結束的時候。對不起,我需要首先完成工作。 –

+0

我衝你詳細的演練。現在非常清楚。非常感謝你的時間和解釋。 – Cyril