我有这样的表(值列值分隔为' @#@')
Id | Values
1 | abc@#@def@#@ghi@#@
2 | def@#@ghi@#@xyz@#@
3 | abc@#@def@#@xyz@#@
现在我希望结果计数为
abc = 2
def = 3
xyz = 2
我该怎么做?
答案 0 :(得分:0)
如果你知道要查找的子字符串值,那就很容易了。
select string,
(
length(group_concat(values)) -- length of whole thing
-length(group_concat(replace(values, string, '')) -- length of whole thing without searched string
)-- substraction equals length of string*count of strings
/length(string) -- length of string
as string_count
from values
cross join
(select abc as string
union all select def ...)
group by 1
您可能还需要使用
扩展max group concatSET SESSION group_concat_max_len = 1000000;
如果您没有这些值,我建议您查看'mysql explode',Can you split/explode a field in a MySQL query? 并预先创建一个包含这些值(不同)的表
答案 1 :(得分:0)
可以做但有点乱。
首先,生成一个大于分隔字段中可能值数的数字范围。然后将其与您的桌子交叉加入。
将其拆分的基础知识如下(假设在这种情况下最多有100个分隔值): -
SELECT Id, SUBSTRING_INDEX(SUBSTRING_INDEX(sometable.`values`, '@#@', sub0.aNum), '@#@', -1)
FROM sometable
INNER JOIN
(
SELECT 1 + units.i + tens.i * 10 AS aNum
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
) sub0
ON ((LENGTH(sometable.`values`) - LENGTH(REPLACE(sometable.`values`, '@#@', ''))) / 3) >= sub0.aNum;
然后可以扩展它以获得计数: -
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(sometable.`values`, '@#@', sub0.aNum), '@#@', -1) AS the_value, COUNT(sometable.id)
FROM sometable
INNER JOIN
(
SELECT 1 + units.i + tens.i * 10 AS aNum
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
) sub0
ON ((LENGTH(sometable.`values`) - LENGTH(REPLACE(sometable.`values`, '@#@', ''))) / 3) >= sub0.aNum
GROUP BY the_value;
如果分隔值只能在任何行中出现一次,您可以简化此操作: -
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(sometable.`values`, '@#@', sub0.aNum), '@#@', -1) AS the_value, COUNT(DISTINCT sometable.id)
FROM sometable
CROSS JOIN
(
SELECT 1 + units.i + tens.i * 10 AS aNum
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
) sub0
GROUP BY the_value;
另一种可能性是,如果您有一个包含值列表的表: -
SELECT possible_values.avalue AS the_value, COUNT(DISTINCT sometable.id)
FROM sometable
INNER JOIN possible_values
ON FIND_IN_SET(possible_values.avalue, REPLACE(sometable.`values`, '@#@', ','))
GROUP BY the_value;
但是,一般情况下,最好的情况是避免使用包含分隔值的字段。它们是数据库规范化程度不高的标志。