我们在mysql数据库中有一个用户配置文件表,其中一个字段是跟踪用户组的SET
列。
表结构是:
CREATE TABLE IF NOT EXISTS `users_profiles` (
`userId` mediumint(9) NOT NULL DEFAULT '0',
`birthday` date DEFAULT NULL,
`groups` set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20')
);
我想在排序的降序列表中获取最受欢迎的群组,但是我们使用SET
列的事实使得使用COUNT
等函数有点困难。
我可以通过运行此查询来获取特定的组计数:
SELECT count(NULLIF(`interests` & 1,0)) as Count1stVal FROM users_profiles;
但是,我不想为每个组运行查询,然后计算最受欢迎的组
答案 0 :(得分:1)
我有一个建议,但不是实际的代码(因为我不熟悉set数据类型)。
首先,创建一个临时表或子查询,该集合的每个元素都有一行。每行在其集合中都具有该元素。称这个元素。
其次,执行以下查询:
select e.element, count(*)
from user_profiles up join
Elements e
on up.groups like concat('%', e.element, '%')
group by e.element
order by 2 desc
现在,唯一的问题是您的设定值相互重叠。所以,你有“1”和“10”,所以这不会有用。您可以执行以下操作之一来解决此问题。
使用“&”操作和生成的数字列表。在这种情况下,on语句将更改为:
on up.groups& e.element> 0
页面http://www.vbmysql.com/articles/mysql/the-mysql-set-datatype概述了您可以使用集合执行的操作。这也解释了为什么他们经常气馁。 。 。因为它们不提供规范化表的功能。
答案 1 :(得分:1)
这样的事情应该有效:
SELECT
groups, # get the group number
COUNT(groups) AS group_cnt # use this for sorting
FROM users_profiles
GROUP BY groups
ORDER BY group_cnt DESC
我在这台机器上没有服务器,所以我无法测试它,但我认为它应该按预期工作。
编辑:只有当组列中只有一个值时,查询才有效。
如果你有一个不同的表,其中组将被列为id与集合中的数字相对应的条目,你可以这样做:
SELECT
g.id, # the group id corresponds to the groups in the set
COUNT(up.userId) as g_cnt # count the number of users with the group
FROM (
users_profiles up,
groups g
)
WHERE
FIND_IN_SET(g.id, up.groups) > 0
GROUP BY g.id
ORDER BY g_cnt DESC
但是如果你要介绍一个群组表,那么最好将其规范化为用户和群组之间的多对多关系