SQL 中的正则表达式
Regular expressions in TSQL
在列 e_vis_name
的单元格中,我有组织结构,其中部门用 \
符号划分,例如
- Moscow\Direction
- Yaroslavl\Sales
- Omsk\Commercial center\Sales
我需要删除第一个 \ 符号后的所有内容以获得以下结果:
- 莫斯科
- 雅罗斯拉夫
- 鄂木斯克
我该怎么做?
您可以像这样使用 LEFT and CHARINDEX 的组合:
SELECT LEFT(colname, CHARINDEX('\', colname)-1) FROM table
编辑: 如果你没有 \
符号,如果你只想获取整列,你可以这样做:
SELECT
CASE WHEN CHARINDEX('\', colname) > 0 THEN LEFT(colname, CHARINDEX('\', colname)-1)
ELSE ISNULL(colname, '')
END
FROM table
这表示,"If there is a \
, then take the characters up to that point, otherwise take the whole column. And if the column is NULL
then just set an empty string."
我相信您可以根据自己的目的进行调整。
有很多选项可以帮助您实现所需,下面是其中的几个示例
--------------------------------------------------------------------------------
-- TEMP TABLE WITH DATA SAMPLE
DECLARE @table AS TABLE ( Division VARCHAR(100) )
INSERT INTO @table ( Division )
VALUES ( 'Moscow\Direction' )
, ( 'Yaroslavl\Sales' )
, ( 'Omsk\Commercial center\Sales' )
, ( 'Voronezh' )
--------------------------------------------------------------------------------
-- variant using PARSENAME
SELECT REVERSE(PARSENAME(REVERSE(REPLACE(Division, '\', '.')), 1)) AS Town
FROM @table AS T
-------------------------------------------------------------------------------
-- variant using SUBSTRING AND CHARINDEX
SELECT SUBSTRING(division, 1,
CASE WHEN CHARINDEX('\', division) = 0 THEN LEN(Division)
ELSE CHARINDEX('\', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using SUBSTRING AND PATINDEX
SELECT SUBSTRING(division, 1,
CASE WHEN PATINDEX('%\%', division) = 0 THEN LEN(Division)
ELSE PATINDEX('%\%', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using LEFT AND PATINDEX
SELECT LEFT(division,
CASE WHEN PATINDEX('%\%', division) = 0 THEN LEN(Division)
ELSE PATINDEX('%\%', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using LEFT AND CHARINDEX
SELECT LEFT(division,
CASE WHEN CHARINDEX('\', division) = 0 THEN LEN(Division)
ELSE CHARINDEX('\', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using recursive cte, substring, top with ties by Row_number()
;
WITH tally
AS (SELECT n = 1
UNION ALL
SELECT n = n + 1
FROM tally
WHERE n < 100)
SELECT TOP 1 WITH TIES SUBSTRING(A.Division,1,B.n-1) AS Town
FROM @table AS A
JOIN tally AS B ON SUBSTRING(A.Division + '\', B.n , 1)= '\'
ORDER BY ROW_NUMBER() OVER (PARTITION BY A.Division ORDER BY B.n)
--------------------------------------------------------------------------------
-- variant using recursive cte, substring, row_number, subquery
;
WITH tally
AS (SELECT n = 1
UNION ALL
SELECT n = n + 1
FROM tally
WHERE n < 100)
SELECT T.TOWN
FROM (SELECT SUBSTRING(A.Division,1,B.n-1) AS TOWN,
ROW_NUMBER() OVER (PARTITION BY A.Division ORDER BY B.n) AS RN
FROM @table AS A JOIN tally AS B ON SUBSTRING(A.Division + '\', B.n , 1)= '\'
) AS T
WHERE RN = 1
作为一些备选方案:
使用LEFT
:
REPLACE(LEFT(e_vis_name, CHARINDEX('\', e_vis_name + '\', 1)), '\', '')
使用SUBSTRING
:
REPLACE(SUBSTRING(e_vis_name, 1, CHARINDEX('\', e_vis_name + '\', 1)), '\', '')
使用STUFF
:
STUFF(e_vis_name + '\', CHARINDEX('\', e_vis_name + '\', 1), 512, '')
使用PARSENAME
:
REVERSE(PARSENAME(REVERSE(REPLACE(e_vis_name, '\','.')), 1))
-- or REPLACE(REVERSE(PARSENAME(REPLACE(REVERSE(REPLACE(e_vis_name, '.', CHAR(8))), '\','.'), 1)), CHAR(8), '.')
或
PARSENAME(REPLACE(e_vis_name, '\','.'), LEN(e_vis_name) - LEN(REPLACE(e_vis_name, '\', '')) + 1)
-- or REPLACE(PARSENAME(REPLACE(REPLACE(e_vis_name, '.', CHAR(8)), '\','.'), LEN(e_vis_name) - LEN(REPLACE(e_vis_name, '\', '')) + 1) , CHAR(8), '.')
在列 e_vis_name
的单元格中,我有组织结构,其中部门用 \
符号划分,例如
- Moscow\Direction
- Yaroslavl\Sales
- Omsk\Commercial center\Sales
我需要删除第一个 \ 符号后的所有内容以获得以下结果:
- 莫斯科
- 雅罗斯拉夫
- 鄂木斯克
我该怎么做?
您可以像这样使用 LEFT and CHARINDEX 的组合:
SELECT LEFT(colname, CHARINDEX('\', colname)-1) FROM table
编辑: 如果你没有 \
符号,如果你只想获取整列,你可以这样做:
SELECT
CASE WHEN CHARINDEX('\', colname) > 0 THEN LEFT(colname, CHARINDEX('\', colname)-1)
ELSE ISNULL(colname, '')
END
FROM table
这表示,"If there is a \
, then take the characters up to that point, otherwise take the whole column. And if the column is NULL
then just set an empty string."
我相信您可以根据自己的目的进行调整。
有很多选项可以帮助您实现所需,下面是其中的几个示例
--------------------------------------------------------------------------------
-- TEMP TABLE WITH DATA SAMPLE
DECLARE @table AS TABLE ( Division VARCHAR(100) )
INSERT INTO @table ( Division )
VALUES ( 'Moscow\Direction' )
, ( 'Yaroslavl\Sales' )
, ( 'Omsk\Commercial center\Sales' )
, ( 'Voronezh' )
--------------------------------------------------------------------------------
-- variant using PARSENAME
SELECT REVERSE(PARSENAME(REVERSE(REPLACE(Division, '\', '.')), 1)) AS Town
FROM @table AS T
-------------------------------------------------------------------------------
-- variant using SUBSTRING AND CHARINDEX
SELECT SUBSTRING(division, 1,
CASE WHEN CHARINDEX('\', division) = 0 THEN LEN(Division)
ELSE CHARINDEX('\', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using SUBSTRING AND PATINDEX
SELECT SUBSTRING(division, 1,
CASE WHEN PATINDEX('%\%', division) = 0 THEN LEN(Division)
ELSE PATINDEX('%\%', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using LEFT AND PATINDEX
SELECT LEFT(division,
CASE WHEN PATINDEX('%\%', division) = 0 THEN LEN(Division)
ELSE PATINDEX('%\%', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using LEFT AND CHARINDEX
SELECT LEFT(division,
CASE WHEN CHARINDEX('\', division) = 0 THEN LEN(Division)
ELSE CHARINDEX('\', division) - 1
END) AS Town
FROM @table AS T
--------------------------------------------------------------------------------
-- variant using recursive cte, substring, top with ties by Row_number()
;
WITH tally
AS (SELECT n = 1
UNION ALL
SELECT n = n + 1
FROM tally
WHERE n < 100)
SELECT TOP 1 WITH TIES SUBSTRING(A.Division,1,B.n-1) AS Town
FROM @table AS A
JOIN tally AS B ON SUBSTRING(A.Division + '\', B.n , 1)= '\'
ORDER BY ROW_NUMBER() OVER (PARTITION BY A.Division ORDER BY B.n)
--------------------------------------------------------------------------------
-- variant using recursive cte, substring, row_number, subquery
;
WITH tally
AS (SELECT n = 1
UNION ALL
SELECT n = n + 1
FROM tally
WHERE n < 100)
SELECT T.TOWN
FROM (SELECT SUBSTRING(A.Division,1,B.n-1) AS TOWN,
ROW_NUMBER() OVER (PARTITION BY A.Division ORDER BY B.n) AS RN
FROM @table AS A JOIN tally AS B ON SUBSTRING(A.Division + '\', B.n , 1)= '\'
) AS T
WHERE RN = 1
作为一些备选方案:
使用LEFT
:
REPLACE(LEFT(e_vis_name, CHARINDEX('\', e_vis_name + '\', 1)), '\', '')
使用SUBSTRING
:
REPLACE(SUBSTRING(e_vis_name, 1, CHARINDEX('\', e_vis_name + '\', 1)), '\', '')
使用STUFF
:
STUFF(e_vis_name + '\', CHARINDEX('\', e_vis_name + '\', 1), 512, '')
使用PARSENAME
:
REVERSE(PARSENAME(REVERSE(REPLACE(e_vis_name, '\','.')), 1))
-- or REPLACE(REVERSE(PARSENAME(REPLACE(REVERSE(REPLACE(e_vis_name, '.', CHAR(8))), '\','.'), 1)), CHAR(8), '.')
或
PARSENAME(REPLACE(e_vis_name, '\','.'), LEN(e_vis_name) - LEN(REPLACE(e_vis_name, '\', '')) + 1)
-- or REPLACE(PARSENAME(REPLACE(REPLACE(e_vis_name, '.', CHAR(8)), '\','.'), LEN(e_vis_name) - LEN(REPLACE(e_vis_name, '\', '')) + 1) , CHAR(8), '.')