我想找到最受欢迎的价值并按月订购结果。 我的意思是,按月出现的价值最多。
我做了很多研究和一些答案,找到最受欢迎的产品。通常,解决方案是分组1和按顺序排列1。 像这样:Find most frequent value in SQL column
这是我的示例表。 让我们尝试找到每个人最喜欢的颜色。
Table 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月份,汤姆喜欢黄色(他选择了两次而不是一次红色),他更喜欢蓝色的行军。 而山姆最喜欢的一个是4月粉红色,黄色是3月。
所以我想要一张返回的桌子 其中Name = Tom
月/颜色
04 /黄色
03 /蓝
并且Name = Sam
月/颜色
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 / red / 1
03 /蓝/ 1
实际上它正是我需要的,除了我不想要的第二行。 我想到了max(count())的东西,但mysql不允许这样做。
任何人? 非常感谢。
答案 0 :(得分: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 |
+------+-------+--------+
编辑:添加说明/演练
这里的主要目标是我们想要收集我们聚合的每组数据(在这种情况下,每个名称/月的组合)并根据它们有多少行来排序颜色。然后,我们想要在这些结果中插入一个新列,并明确排列哪种颜色具有最多行,哪种颜色具有下一行,等等。
当我们开始时,我们还没准备好对这些事情进行排名,我们有多行说“黄色”,但我们希望数据显示“黄色有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 |
+------+-------+--------+