Select 使用正则表达式匹配的字符串的特定部分
Select specific portion of string using Regex match
请考虑以下 table。我试图仅检索 Tax
字符串中的欧元金额。一些记录的大小差异较大,但浮点数始终存在。
OrderID SKU Price Tax
**** **** **** [<TV<standard#21.0#false#21.36#EUR>VT>]
**** **** **** [<TV<standard#21.0#false#7.21#EUR>VT>]
**** **** **** [<TV<standard#17.0#false#5.17#EUR>VT>]
我写了一个匹配我需要的正则表达式:\d+\W\d+
returns 我在字符串中有两个浮点值。在 Oracle SQL 中,我可以通过如下查询简单地获得第二次出现:
SELECT REGEXP_SUBSTR(column, '\d+\W\d+',1,2) FROM table
使用上述方法,我检索了这三个记录的 21.36
、7.21
和 5.17
。
如何使用 SQL 服务器实现此目的?
显然正则表达式可能是此处的首选工具。但是 SQL 服务器没有太多的本地正则表达式支持。这是一个使用 PATINDEX
和 CHARINDEX
的纯 SQL 服务器解决方案。它有点冗长,但可以完成工作:
SELECT
SUBSTRING(Tax,
CHARINDEX('#', Tax, PATINDEX('%[0-9]#%', Tax) + 3) + 1,
CHARINDEX('#', Tax, CHARINDEX('#', Tax, PATINDEX('%[0-9]#%', Tax) + 3) + 1) -
CHARINDEX('#', Tax, PATINDEX('%[0-9]#%', Tax) + 3) - 1)
FROM yourTable;
请尝试以下解决方案。
该方法使用 XML 对税收列进行标记化。
它为每一行生成如下所示的 XML:
<root>
<r>[<TV<standard</r>
<r>21.0</r>
<r>false</r>
<r>21.36</r>
<r>EUR>VT>]</r>
</root>
第 4 个 r 元素是有问题的货币价值。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Tax VARCHAR(MAX));
INSERT INTO @tbl (Tax) VALUES
('[<TV<standard#21.0#false#21.36#EUR>VT>]'),
('[<TV<standard#21.0#false#7.21#EUR>VT>]'),
('[<TV<standard#17.0#false#5.17#EUR>VT>]');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = '#';
SELECT t.*
, c.value('(/root/r[4]/text())[1]', 'DECIMAL(10,2)') AS result
FROM @tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(tax, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c);
输出
+----+-----------------------------------------+--------+
| ID | Tax | result |
+----+-----------------------------------------+--------+
| 1 | [<TV<standard#21.0#false#21.36#EUR>VT>] | 21.36 |
| 2 | [<TV<standard#21.0#false#7.21#EUR>VT>] | 7.21 |
| 3 | [<TV<standard#17.0#false#5.17#EUR>VT>] | 5.17 |
+----+-----------------------------------------+--------+
请考虑以下 table。我试图仅检索 Tax
字符串中的欧元金额。一些记录的大小差异较大,但浮点数始终存在。
OrderID SKU Price Tax
**** **** **** [<TV<standard#21.0#false#21.36#EUR>VT>]
**** **** **** [<TV<standard#21.0#false#7.21#EUR>VT>]
**** **** **** [<TV<standard#17.0#false#5.17#EUR>VT>]
我写了一个匹配我需要的正则表达式:\d+\W\d+
returns 我在字符串中有两个浮点值。在 Oracle SQL 中,我可以通过如下查询简单地获得第二次出现:
SELECT REGEXP_SUBSTR(column, '\d+\W\d+',1,2) FROM table
使用上述方法,我检索了这三个记录的 21.36
、7.21
和 5.17
。
如何使用 SQL 服务器实现此目的?
显然正则表达式可能是此处的首选工具。但是 SQL 服务器没有太多的本地正则表达式支持。这是一个使用 PATINDEX
和 CHARINDEX
的纯 SQL 服务器解决方案。它有点冗长,但可以完成工作:
SELECT
SUBSTRING(Tax,
CHARINDEX('#', Tax, PATINDEX('%[0-9]#%', Tax) + 3) + 1,
CHARINDEX('#', Tax, CHARINDEX('#', Tax, PATINDEX('%[0-9]#%', Tax) + 3) + 1) -
CHARINDEX('#', Tax, PATINDEX('%[0-9]#%', Tax) + 3) - 1)
FROM yourTable;
请尝试以下解决方案。
该方法使用 XML 对税收列进行标记化。 它为每一行生成如下所示的 XML:
<root>
<r>[<TV<standard</r>
<r>21.0</r>
<r>false</r>
<r>21.36</r>
<r>EUR>VT>]</r>
</root>
第 4 个 r 元素是有问题的货币价值。
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Tax VARCHAR(MAX));
INSERT INTO @tbl (Tax) VALUES
('[<TV<standard#21.0#false#21.36#EUR>VT>]'),
('[<TV<standard#21.0#false#7.21#EUR>VT>]'),
('[<TV<standard#17.0#false#5.17#EUR>VT>]');
-- DDL and sample data population, end
DECLARE @separator CHAR(1) = '#';
SELECT t.*
, c.value('(/root/r[4]/text())[1]', 'DECIMAL(10,2)') AS result
FROM @tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' +
REPLACE(tax, @separator, ']]></r><r><![CDATA[') +
']]></r></root>' AS XML)) AS t1(c);
输出
+----+-----------------------------------------+--------+
| ID | Tax | result |
+----+-----------------------------------------+--------+
| 1 | [<TV<standard#21.0#false#21.36#EUR>VT>] | 21.36 |
| 2 | [<TV<standard#21.0#false#7.21#EUR>VT>] | 7.21 |
| 3 | [<TV<standard#17.0#false#5.17#EUR>VT>] | 5.17 |
+----+-----------------------------------------+--------+