我很感激您的输入,以帮助我计算MySql中SET类型的唯一值。我有一个名为"功能"定义为SET字段如下:
CREATE TABLE cars (features SET('power steering', 'power locks', 'satellite radio', 'power windows', 'sat nav', 'turbo'));
当我填写此表时,由于这些功能并不相互排斥,因此我将获得包含这些功能中的两个或更多功能组合的记录。例如:
Car 1具有动力转向和电动车窗,但没有其余功能。 车2具有所有功能。 除了卫星导航和涡轮增压外,Car 3具有所有功能。
我想要做的是获取表中所有单个列出的功能的列表,包括使用GROUP BY子句以类似方式与SELECT语句关联的记录计数。因此,按照上面的示例,我应该能够得到以下结果:
features |count
---------------+------
power steering | 3 //All cars have this feature
power locks | 2 //Only cars 2 and 3 have it
satellite radio| 2 //Only cars 2 and 3 have it
power windows | 3
sat nav | 1 //only car 2 has it
turbo | 1 //only car 2 has it
我尝试使用以下查询,期望获得上述结果:
SELECT features, COUNT(features) FROM cars GROUP BY features;
然而,不是我期望的,我得到了每个现有功能组合的计数:
features |count
------------------------------------------------+--------
power steering, power windows | 1 //i.e. only 1 car has
| //only these 2 features
| //(car 1 in this example)
|
------------------------------------------------+-------
power steering, power locks, satellite radio, |
power windows, sat nav, turbo | 1
------------------------------------------------+-------
power steering, power locks, satellite radio, |
power windows | 1
所以,问题是:有没有办法获得每个单一功能的计数,如第一个表所示,使用一个MySQL查询?我可以通过执行一个查询来实现对于每个功能,但我确信必须有一种避免这种麻烦的方法。有人可能建议为功能和连接使用不同的表,但是在此时不可能不会严重影响项目的其余部分。提前谢谢!
答案 0 :(得分:1)
通常,我们使用FIND_IN_SET
函数。
您可以使用这样的查询来返回指定的结果:
SELECT f.feature
, COUNT(1)
FROM ( SELECT 'power steering' AS feature
UNION ALL SELECT 'power locks'
UNION ALL SELECT 'satellite radio'
UNION ALL SELECT 'power windows'
UNION ALL SELECT 'sat nav'
UNION ALL SELECT 'turbo'
) f
JOIN cars c
ON FIND_IN_SET(f.feature,c.features)>0
GROUP BY f.feature
ORDER BY f.feature
您可以省略>0
并获得相同的结果。此查询省略"零计数":具有"功能的行#34;这对任何一辆车来说都不会出现。要获得这些内容,您可以使用外部联接(在LEFT
之前添加JOIN
关键字,而不是在SELECT列表中添加COUNT(1)
,COUNT(expr)
其中expr
是来自cars
的{{1}}列,或者是找到匹配行时非NULL的其他表达式,以及找不到匹配行时的NOT NULL
。
答案 1 :(得分:1)
SELECT set_list.features, COUNT(cars.features) FROM
(SELECT TRIM("'" FROM SUBSTRING_INDEX(SUBSTRING_INDEX(
(SELECT TRIM(')' FROM SUBSTR(column_type, 5)) FROM information_schema.columns
WHERE table_name = 'cars' AND column_name = 'features'),
',', @r:=@r+1), ',', -1)) AS features
FROM (SELECT @r:=0) deriv1,
(SELECT ID FROM information_schema.COLLATIONS) deriv2
HAVING @r <=
(SELECT LENGTH(column_type) - LENGTH(REPLACE(column_type, ',', ''))
FROM information_schema.columns
WHERE table_name = 'cars' AND column_name = 'features')) set_list
LEFT OUTER JOIN cars
ON FIND_IN_SET(set_list.features, cars.features) > 0
GROUP BY set_list.features
改编自:
MySQL: Query for list of available options for SET
我的查询以上述帖子中的SQL为基础,获取可用列值的列表。所有缩进的SQL都是一个查询,如果单独执行它,你将获得列表,我从中创建一个结果集,我称之为#34; set_list&#34;。我只是原样复制了那个查询,但它基本上做了大量的字符串操作来获取列表 - 正如Mike Brant建议的那样,如果将列表放入另一个表中,代码会更简单(但可能只是不动态) ,刚刚加入。
然后我将set_list重新加入cars表,将set_list中的每个项目与包含该功能的汽车中的行连接起来 - FIND_IN_SET()。它是一个外部联接,所以如果没有表示集合列表中的任何内容,那么它将在那里计数为零。