我有带序列的字符串。理想的字符串是 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;
答案 0 :(得分:2)
一种方法是使用AVAssetReaderOutput
:
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;
更高级的表单(如果您不喜欢嵌套多个替换):
┌───────┬─────────────┐
│ 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;
答案 1 :(得分:1)
我不会使用正则表达式。使用C#或其他编程语言会更快,但这应该可以。
注意:这不会处理具有错误数据的seq0。
ALTER FUNCTION F_GetPattern
(
@Sequence VARCHAR(100)
)
RETURNS
VARCHAR(1000)
AS
BEGIN
DECLARE @T1 VARCHAR(10)
DECLARE @T2 VARCHAR(10)
DECLARE @I1 INT
DECLARE @I2 INT = 0
DECLARE @Size INT = 4
DECLARE @Index INT = 0
DECLARE @Result VARCHAR(100) = ''
SET @T1 = SUBSTRING(@Sequence, 1, 2)
SET @T2 = SUBSTRING(@Sequence, 4, 2)
SET @I1 = CAST(@T1 AS INT)
IF (LEN(@Sequence ) > 3)
SET @I2 = CAST(@T2 AS INT)
WHILE @Index < @Size
BEGIN
IF @Index > 0 AND @Index < @Size
SET @Result = @Result + '-'
IF @Index + 1 = @I1
SET @Result = @Result + @T1
ELSE
BEGIN
IF @Index + 1 = @I2
SET @Result = @Result + @T2
ELSE
SET @Result = @Result + 'xx'
END
SET @Index = @Index + 1
END
return @Result
END
GO
SELECT seq0, DBO.F_GetPattern(seq0) FROM t0
GO
答案 2 :(得分:1)
虽然我上面的回答很好,但@Lukasz Szozda的方法要简单得多。如果您只有几个条目,请帮个忙,并像这样简单!
如果您需要一个可以扩展到更大序列的更健壮的选项,那么这里是另一个使用STUFF(...)的选项。如果序列变大并且必须对大量记录执行此操作,则它最有可能比其他选项更有效。
CREATE FUNCTION F_GetPattern
(
@Sequence VARCHAR(100)
)
RETURNS
VARCHAR(1000)
AS
BEGIN
DECLARE @T1 VARCHAR(10)
DECLARE @T2 VARCHAR(10)
DECLARE @I1 INT
DECLARE @I2 INT = 0
DECLARE @Result VARCHAR(100) = 'xx-xx-xx-xx'
SET @T1 = SUBSTRING(@Sequence, 1, 2)
SET @T2 = SUBSTRING(@Sequence, 4, 2)
SET @I1 = CAST(@T1 AS INT)
IF (LEN(@Sequence ) > 3)
SET @I2 = CAST(@T2 AS INT)
SET @Result = STUFF(@Result, @I1 * 3 -2, 2, @T1)
IF @I2 > 0
SET @Result = STUFF(@Result, @I2 * 3 -2, 2, @T2)
return @Result
END
GO
SELECT seq0, DBO.F_GetPattern(seq0) FROM t0
GO