我的源表如下所示:
Source table:
ID Col
---- --------------
1 TAMATO / INNPU# HH55555
2 PATATO/9-1 666 000 0000
3 CARLI 1111110000/0002222000
4 BRINZAL 000-8888(CELL)
5 LADY INDAP444444444
6 PUMKIN INNDP#123456789
7 HELLO/CELL#9-1-000-000-9900
我想按记录阅读记录,并希望根据以下条件将字段移动到另一个表:
1. If there is a(or more) space or any special chars(e.g. /) before the
number.Then move the number part(starting from number till end of the
string) to the new table/column.
2.For any String(record) contain "CELL" or "AP" or "PU" or "ND" or "DP":
then, Starting from the number, move 6 chars backward and within these 6
chars, If any String(record) contain "CELL" or "AP" or "PU" or "ND" or
"DP" - move these records (staring from "CELL" or "AP" or "PU" or "ND" or
"DP" till end of the string) to another table/column.
所以我的决赛桌看起来如下所示。
结果表:
ID Col
---- --------------
1 PU# HH55555
2 9-1 666 000 0000
3 1111110000/0002222000
4 000-8888(CELL)
5 AP444444444
6 DD#123456789
7 CELL#9-1-000-000-9900
我写了以下查询;但是,它看起来有一些问题。
DECLARE @TableName VARCHAR(100)
DECLARE @find CURSOR
SET @FIND = CURSOR FOR SELECT col FROM Source_Table WHERE col like '%[0-
9]%';
OPEN @find;
FETCH NEXT FROM @find INTO @TableName;
DECLARE @Data VARCHAR(max)
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @ParsedData VARCHAR(5)
DECLARE @CompVal1 VARCHAR(5) = 'CELL#'
SET @Data = (SELECT col FROM Source_Table WHERE col = @TableName)
SET @ParsedData = (SELECT right(left(@Data, PATINDEX('%[0-9]%',
@Data ) - 1),6))
IF (@ParsedData = @CompVal1)
SELECT @ParsedData
SELECT @Data, SUBSTRING(@Data, PATINDEX('%[0-9]%', @Data ),
(LEN(@Data)-1))
FETCH NEXT FROM @find INTO @TableName;
END;
CLOSE @find;
DEALLOCATE @find;
更改了我的查询,如下所示,仍无法实现此目的:
declare @result table
(
Col varchar(max)
);
declare
@C as cursor,
@Col as varchar(max),
@Data VARCHAR(max);
set @C = cursor fast_forward for
SELECT Col FROM Source_Table WHERE Col like '%[0-9]%';
open @C;
fetch next from @C into @Col;
select @Data = @Col
while @@FETCH_STATUS = 0
begin
DECLARE @ParsedData VARCHAR(5)
--DECLARE @CompVal1 VARCHAR(5) = 'DPP# '
--SET @ParsedData = (SELECT right(left(@Data, PATINDEX('%[0-9]%', @Data
-- ) - 1),5))
--IF (@ParsedData = @CompVal1)
--SELECT @ParsedData
--SELECT @Data, SUBSTRING(@Data, PATINDEX('%[0-9]%', @Data ),
--(LEN(@Data)-1))
SET @ParsedData = (SELECT left(@Data, PATINDEX('%[0-9]%', @Data ) - 1))
set @Col = @ParsedData
insert into @result values(@Col)
fetch next from @C into @Col;
END;
CLOSE @C;
DEALLOCATE @C;
Select * from @result
我如何根据我的结果表实现?
注意:我的表有100k这样的记录;没有光标的任何其他方式也会有所帮助。 感谢。
答案 0 :(得分:1)
以下是涵盖条件1和条件2的“CELL”/“AP”部分的查询。
此查询使用COALESCE
来获得最大的简洁性,可以用CASE
表达式替换。
Number 1000000
是一个任意大数字,用于确保SUBSTRING
返回整个字符串。如果您的字符串可能大于1000000个字符,请将数字更改为更大的字符串。
DROP TABLE #TestData
CREATE TABLE #TestData( Col VARCHAR( 100 ))
INSERT INTO #TestData
VALUES
( 'PU# HH55555 ' ),
( '9-1 666 000 0000 '),
( '1111110000/0002222000 '),
( '000-8888(CELL)'),
( 'AP444444444 '),
( 'DD#123456789 '),
( 'CELL#9-1-000-000-9900'),
( 'AP 9-1-000-000-9900'),
( 'AP 9-1-000-000-9900'),
( 'asdf'),
('')
;WITH SomeNumbers AS(
SELECT
Col,
COALESCE(
-- Conditions execute in order of appearance i.e. try the first match if not matched, then then try the 2nd etc.
CASE WHEN PATINDEX( '%[0-9]%', SUBSTRING( Col, NULLIF( PATINDEX( '%CELL%[0-9]%', Col ), 0 ), 7 )) > 0 THEN SUBSTRING( Col, PATINDEX( '%CELL%[0-9]%', Col ), 1000000 ) END,
CASE WHEN PATINDEX( '%[0-9]%', SUBSTRING( Col, NULLIF( PATINDEX( '%AP%[0-9]%', Col ), 0 ), 7 )) > 0 THEN SUBSTRING( Col, PATINDEX( '%AP%[0-9]%', Col ), 1000000 ) END,
/*
Add your remaning conditions here using above conditions as an exmaple
*/
SUBSTRING( Col , NULLIF( PATINDEX( '%[ /][0-9]%', Col ), 0 ) + 1, 1000000 )
) AS ParsedNumber
FROM #TestData
)
SELECT *
FROM SomeNumbers
WHERE NOT ParsedNumber IS NULL
条件如何运作:
COALESCE( ...
- 返回第一个非NULL表达式。 COALESCE
内的所有匹配条件都以这种方式写入,以便在字符串与给定条件不匹配时返回NULL,从而允许评估下一个条件。
SUBSTRING( Col , NULLIF( PATINDEX( '%[ /][0-9]%', Col ), 0 ) + 1, 1000000 )
:
PATINDEX( '%[ /][0-9]%', Col )
- 查找时的模式
第一个字符是任何字符是[和]之间的列表
紧接着是一个数字角色。如果找到模式,则返回
此模式开始的字符位置,如果模式不是,则为0
找到。NULLIF
返回0,则PATINDEX
返回NULL
返回PATINDEX
SUBSTRING
- 返回
以PATINDEX
OR返回的字符位置开头的字符串
如果未找到模式,则为NULL(因此NULLIF
返回NULL)。 CASE WHEN PATINDEX( '%[0-9]%', SUBSTRING( Col, PATINDEX( '%CELL%[0-9]%', Col ), 7 )) > 0 THEN SUBSTRING( Col, PATINDEX( '%CELL%[0-9]%', Col ), 1000000 ) END
PATINDEX( '%CELL%[0-9]%', Col )
- 检查是否有单词“CELL”后跟一个数字。其他字符可以出现在单词“CELL”和数字之间。返回单词“CELL”开始的字符位置。SUBSTRING( .., .., 7 )
- 从单词“CELL”开始抓取7个字符。这将是数字前最多可能的6个字符,第7个字符是数字。PATINDEX( '%[0-9]%', ...
- 检查上面选择的7个字符中是否出现数字字符。