2

我们在 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;

但是,我不想为每个组运行查询,然后计算最受欢迎的组

4

2 回答 2

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

但是,如果您要引入组表,那么最好将其规范化为用户和组之间的多对多关系

于 2012-06-28T19:38:15.227 回答
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”,所以这不太行。您可以执行以下操作之一来解决此问题。

  1. 重命名设置值(例如,您的实际表可能没有这个问题)。
  2. 使用“&”操作和生成的数字列表。在这种情况下,on 语句更改为:

    在 up.groups & e.element > 0

该页面http://www.vbmysql.com/articles/mysql/the-mysql-set-datatype很好地概述了您可以使用集合做什么。这也解释了为什么他们经常气馁。. . 因为它们不提供规范化表的功能。

于 2012-06-28T19:30:51.117 回答