mysql - SQL:用假人填充有序字符串序列中的缺失

标签 mysql sql regex replace

我有带序列的字符串。理想的字符串是 01-02-03-04 但在某些记录中我有缺失:

---------
| seq0  |
| ----- |
| 01-04 |
| 02-03 |
| 02-04 |
| 01-04 |
| 02    |
---------    

这些都是例子。任何组合都是可能的。为了更好地识别缺少的内容,我想插入 xx 以获取缺少的内容:

-----------------------
| seq0  | seq1        | 
| ----- | ----------- | 
| 01-04 | 01-xx-xx-04 | 
| 02-03 | xx-02-03-xx | 
| 02-04 | xx-02-xx-04 | 
| 01-04 | 01-xx-xx-04 | 
| 02    | xx-02-xx-xx | 
-----------------------    

我有一个使用 REGEXP 和 REPLACE 的解决方案(见下文)。但是如果序列比较长(比如:01-...-12),写代码会比较麻烦。我想知道是否有另一种方法可以做到这一点。我可以使用短过程 (MySQL),但也许有一种优雅的方法可以使用(几乎)纯 SQL 来做到这一点。

生成表格的代码:

DROP TABLE IF EXISTS t0;
CREATE TABLE t0 (
  seq0       VARCHAR(100)
, seq1      VARCHAR(100)
);

INSERT INTO t0 (seq0) VALUES 
 ('01-04')
,('02-03')
,('02-04') 
,('01-04')
,('02')
;

SELECT * FROM t0;

UPDATE t0
SET seq1 = seq0
    -- insert xx       
    , seq1 = CASE WHEN seq1 REGEXP '01-03' THEN REPLACE(seq1,'01-03','01-xx-03') ELSE seq1 END
    , seq1 = CASE WHEN seq1 REGEXP '01-04' THEN REPLACE(seq1,'01-04','01-xx-xx-04') ELSE seq1 END   

    , seq1 = CASE WHEN seq1 REGEXP '02-04' THEN REPLACE(seq1,'02-04','02-xx-04') ELSE seq1 END   

    -- right pad xx
    , seq1 = CASE WHEN seq1 REGEXP '01$' THEN REPLACE(seq1,'01','01-xx-xx-xx') ELSE seq1 END   
    , seq1 = CASE WHEN seq1 REGEXP '02$' THEN REPLACE(seq1,'02','02-xx-xx') ELSE seq1 END   
    , seq1 = CASE WHEN seq1 REGEXP '03$' THEN REPLACE(seq1,'03','03-xx') ELSE seq1 END   

    -- left pad xx
    , seq1 = CASE WHEN seq1 REGEXP '^02' THEN REPLACE(seq1,'02','xx-02') ELSE seq1 END   
    , seq1 = CASE WHEN seq1 REGEXP '^03' THEN REPLACE(seq1,'03','xx-xx-03') ELSE seq1 END   
    , seq1 = CASE WHEN seq1 REGEXP '^04' THEN REPLACE(seq1,'04','xx-xx-xx-04') ELSE seq1 END   
    ;
SELECT * FROM t0;

最佳答案

一种方法是使用REPLACE:

SELECT seq0,
      REPLACE(REPLACE(REPLACE(
      REPLACE('01-02-03-04',
         CASE WHEN INSTR(seq0, '01') > 0 THEN 'u' ELSE '01' END, 'xx')
        ,CASE WHEN INSTR(seq0, '02') > 0 THEN 'u' ELSE '02' END, 'xx')
        ,CASE WHEN INSTR(seq0, '03') > 0 THEN 'u' ELSE '03' END, 'xx')
        ,CASE WHEN INSTR(seq0, '04') > 0 THEN 'u' ELSE '04' END, 'xx') AS result
FROM t0;

DBFiddle Demo

输出:

┌───────┬─────────────┐
│ seq0  │   result    │
├───────┼─────────────┤
│ 01-04 │ 01-xx-xx-04 │
│ 02-03 │ xx-02-03-xx │
│ 02-04 │ xx-02-xx-04 │
│ 01-04 │ 01-xx-xx-04 │
│ 02    │ xx-02-xx-xx │
└───────┴─────────────┘

编辑

更高级的形式(如果你不喜欢嵌套多个替换):

SELECT seq0, result
FROM (
    SELECT seq0
        ,@u:= REPLACE(IF(@prev_value=seq0, @u,@start_string),
                      IF(INSTR(seq0, sub.c) > 0, 'u', sub.c), 'xx') AS result
        ,@cnt:=IF(@prev_value=seq0,@cnt-1,@l) AS c
        ,@prev_value := seq0
    FROM ( SELECT DISTINCT *
        FROM t0 ,(SELECT '01' AS c UNION SELECT '02' 
                  UNION SELECT '03' UNION SELECT '04') num)sub
    ,(SELECT @u := ''
        ,@prev_value := ''
        ,@start_string := '01-02-03-04'
        ,@l := length(@start_string)-length(replace(@start_string,'-',''))
        ,@cnt := 0
        ) z
    ORDER BY sub.seq0, sub.c
) q
WHERE q.c = 0;

DBFiddle Demo2

输出:

┌───────┬─────────────┐
│ seq0  │   result    │
├───────┼─────────────┤
│ 01-04 │ 01-xx-xx-04 │
│ 02    │ xx-02-xx-xx │
│ 02-03 │ xx-02-03-xx │
│ 02-04 │ xx-02-xx-04 │
└───────┴─────────────┘

关于mysql - SQL:用假人填充有序字符串序列中的缺失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51048094/

相关文章:

mysql - SQL查询帮助: How can i get the column value from other table?

python - 如何编写此正则表达式来匹配整个字符串?

c# - 使用可以嵌入自身的正则表达式进行解析/拆分

regex - 使用 Perl 正则表达式查找和提取多行匹配项

c++ - 如何使用 MySQL C++ 连接器检查 null 或空结果集?

mysql 大小写函数

c# - 无法将属性或索引器 'AnonymousType#1.FirstName' 分配给 -- 它是只读的

c# - 在 C# 中, "SELECT TOP 0 * FROM (/* ... */) s"与 ADO.NET 结合使用是否是确定 SELECT 语句中的列信息的好方法?

php mysql 数据库项名称从另一个数据库调用

mysql - SQL,通过删除具有最低值的行来限制总行数