用于从SET列获取最常用项的SQL查询

时间:2012-06-28 19:08:23

标签: php mysql sql zend-framework

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

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

2 个答案:

答案 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”,所以这不会有用。您可以执行以下操作之一来解决此问题。

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

    on up.groups& e.element> 0

  3. 页面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

但是如果你要介绍一个群组表,那么最好将其规范化为用户和群组之间的多对多关系