数据:user_choices
表
| 身份证|用户标识|选择|
| --------------|--------------|--------------|
| 1|三|一二三|
| 二|五十五|五|
| 三|七八三|二六七|
| 四|四十五|一、四|
| 五|五|一二三四五六七|
我如何查询这个表来分解choices
列,该列只显示值1或2或3或4或7,并按userid
分组,如下所示?
| 用户标识|选择|
| --------------|--------------|
| 三|1|
| 三|二|
| 三|三|
| 七八三|二|
| 七八三|七|
| 四十五|1|
| 四十五|四|
| 五|1|
| 五|二|
| 五|三|
| 五|四|
| 五|七|
我尝试了以下方法,但结果包括5
和6
,应该省略。
select replace(substring(substring_index(uc.choices, ',', 1), CHAR_LENGTH(SUBSTRING_INDEX(uc.choices, ',', -1)), + 1), ',', '') choice,,
uc.userid
from user_choices uc
join (select 1 digit union all select 2 union all select 3 union all select 4 union all select 7) n on length(replace(uc.choices, ',', '')) < length(uc.choices) - n.digit
where choices regexp '[12347]'
order by uc.userid
注意:我知道这里的正则表达式并不完美(例如,匹配22
)。这里的表永远不会接收到这个,所以我认为不需要更严格的正则表达式。
输出:
| 选择|用户标识|
| --------------|--------------|
| 1|三|
| 1|五|
| 1|五|
| 1|五|
| 1|五|
| 二|七八三|
这个尝试是基于this answer到另一个问题,但我不能完全让它为我的场景工作。
非常感谢您的帮助!
2条答案
按热度按时间9avjhtql1#
数字表技术的另一种选择是使用JSON。
诀窍在于,给定CSV字符串的格式(用逗号分隔的数字),我们可以很容易地将它们转换为有效的JSON值,只需用方括号将它们括起来;例如
[1,2,3]
是一个有效的JSON数组。然后,我们可以使用方便的JSON函数json_table()
将数组解嵌套到行中。最后一步是过滤。所以:
fiddle
8wigbo562#
我不清楚你的sql到底是怎么失败的,但你似乎没有完全正确地使用这种方法。
首先,您应该只连接与每行中的选择数相匹配的数字(因此,1、2和3表示'1,6,7');要做到这一点,你需要计算逗号的数量,加一(因为比逗号多了一个选择),并与数字进行比较:
你似乎在尝试类似的东西,但不太正确。
其次,要提取第n个选择,您需要使用substring_index来获取前n个选择,并再次使用它来获取最后一个:
我没有理解你的replace/substring到底想做什么,但是double substring_index要简单得多。
所以:
如果你有一些选择,而regexp不够好,你可以使用例如: