我有一个文本字段,如下所示:
option[A]sum[A]g3et[B]
我想获取[ ]
内没有重复的文本。
意思是:
A
B
不能出现像[ [ ] ]
这样的双重案例。
我知道这是一种在数据库中保存数据的可怕方法。我无法更改数据的保存方式。我只需要从本专栏中获取非常具体的(一次性)信息。
我试着这样做:
SELECT substring_index(substring_index(sentence, '[', -1),']', 1)
FROM (SELECT 'THIS[A] IS A TEST' AS sentence) temp;
这给了我A
,但它不适用于许多[]
。
我想过使用正则表达式,但我不知道有多少[ ]
。
我该怎么做?
答案 0 :(得分:5)
这不是DB
的工作,但有可能:
CREATE TABLE tab(id INT, col VARCHAR(100));
INSERT INTO tab(id, col)
VALUES (1, 'option[A]sum[A]g3et[B]'), (2, '[Cosi]sum[A]g3et[ZZZZ]');
SELECT DISTINCT *
FROM (
SELECT id, RIGHT(val, LENGTH(val) - LOCATE('[', val)) AS val
FROM
(
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(t.col, ']', n.n), ']', -1) AS val
FROM tab t
CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
) n
WHERE n.n <= 1 + (LENGTH(t.col) - LENGTH(REPLACE(t.col, ']', '')))
) sub
) s
WHERE val <> ''
ORDER BY ID;
的 SqlFiddleDemo
强>
注意:
根据col
最大长度,您可能需要在CROSS JOIN
部分生成更多数字。现在它高达100。
输出:
工作原理:
CROSS JOIN
]
拆分字符串作为分隔符RIGHT(val, LENGTH(val) - LOCATE('[', val))
将部分删除至[
DISTINCT
值最内层查询:
╔════╦══════════╗
║ id ║ val ║
╠════╬══════════╣
║ 1 ║ option[A ║
║ 1 ║ sum[A ║
║ 1 ║ g3et[B ║
║ 1 ║ ║
╚════╩══════════╝
第二个子查询:
╔════╦═════╗
║ id ║ val ║
╠════╬═════╣
║ 1 ║ A ║
║ 1 ║ A ║
║ 1 ║ B ║
║ 1 ║ ║
╚════╩═════╝
最外层的查询:
╔════╦═════╗
║ id ║ val ║
╠════╬═════╣
║ 1 ║ A ║
║ 1 ║ B ║
╚════╩═════╝
我需要每行查询的结果..不合并
所以添加简单:
WHERE n.n <= 1 + (LENGTH(t.col) - LENGTH(REPLACE(t.col, ']', '')))
AND t.id = ?
编辑2:
请参阅http://sqlfiddle.com/#!9/8ee95/1您的查询部分适用于我的数据。我还将类型更改为longtext。
您想在MySQL中解析JSON。 正如我在解析之前所说并在应用层中获得价值。此答案仅用于演示/玩具目的,并且性能非常低。
如果你仍然坚持使用SQL解决方案:
SELECT id, val,s.n
FROM (
SELECT id, RIGHT(val, LENGTH(val) - LOCATE('[', val)) AS val,n
FROM
(
SELECT id, SUBSTRING_INDEX(SUBSTRING_INDEX(t.col, ']', n.n), ']', -1) AS val, n.n
FROM (SELECT id, REPLACE(col, '[]','') as col FROM tab) t
CROSS JOIN
(
SELECT e.N * 10000 + d.N * 1000 + c.N * 100 + a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) d
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) e
) n
WHERE n.n <= 1 + (LENGTH(t.col) - LENGTH(REPLACE(t.col, ']', '')))
) sub
) s
WHERE val <> ''
GROUP BY id, val
HAVING n <> MAX(n)
ORDER BY id,n;
的 SqlFiddleDemo
强>
输出:
╔═════╦═════════════╦════╗
║ id ║ val ║ n ║
╠═════╬═════════════╬════╣
║ 1 ║ CE31285LV4 ║ 1 ║
║ 1 ║ D32E ║ 3 ║
║ 1 ║ GTX750 ║ 5 ║
║ 1 ║ M256S ║ 7 ║
║ 1 ║ H2X1T ║ 9 ║
║ 1 ║ FMLANE4U4 ║ 11 ║
╚═════╩═════════════╩════╝
编辑3:
那到底做了什么?你为什么需要n
CROSS JOIN
并且整个子查询只是tally表。就这些。如果MySQL
具有生成数字序列的功能(例如generate_series
或预先填充的数字表格,则不需要CROSS JOIN
。
SUBSTRING_INDEX
需要数字表:
<强> SUBSTRING_INDEX(STR,DELIM,计数)强>
在分隔符delim的计数出现之前,从字符串str返回子字符串。 如果count为正数,则返回最终分隔符左侧的所有内容(从左侧开始计算)。如果count为负数,则返回最终分隔符右侧的所有内容(从右侧开始计算) 。搜索delim时,SUBSTRING_INDEX()执行区分大小写的匹配。