English 中文(简体)
如何以最有效率的方式从使用卡片的扼杀中提取这些愤怒?
原标题:What is the most efficient way of extracting these integers from a string using SQL?

我有一份工程数据表,我需要报告描述领域提到的印花长度,以黑体表示:

STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 140 LG C/W 1 NUT, 12 X M24 X 170 LG C/W 1 NUT)
STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (2 X M20 X 80 LG C/W 1 NUT, 6 X M20 X 90 LG C/W 1 NUT)
STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 130 LG C/W 1 NUT, 12 X M24 X 150 LG C/W 1 NUT)
STUD BOLT SET, ASME B1.1, ASTM A193 B7, ASME B1.1, ASTM A194 GR 2H, GALVANISED (28 x 1 3/4" UN8 x 270 LG C/W 1 NUT)

请注意,说明中提到了两个字句长度(例如,第一个记录有“140 LG”和“170 LG”),但我只需要第二段,即“170”,后者也是两者中最大的一个。 虽然该数字的位置在座尾应保持固定的长度,但长度在2至3位数之间。

因此,除了在很多地方使用MID(string,15,3)之外,如果发言确定人数的长短和位置,我没有真正知道如何最好地做到这一点。

任何建议都会受到高度赞赏。

问题回答

Assuming your ssms tag means you are on SQL server, you have only limited support to some version of regular expression (not the POSIX regex).
The below query will do what you want. Its principle is to locate the rightmost occurrence of LG and from there, the 2nd preceding space. The result you want is between these 2 positions.
Refer to the comments for explanation, remove the CTE included to have a complete example and cast the returned value to integer yourself if needed:

WITH MyTable(description) AS (
SELECT  STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 140 LG C/W 1 NUT, 12 X M24 X 170 LG C/W 1 NUT) 
UNION ALL
SELECT  STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (2 X M20 X 80 LG C/W 1 NUT, 6 X M20 X 90 LG C/W 1 NUT) 
UNION ALL
SELECT  STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 130 LG C/W 1 NUT, 12 X M24 X 150 LG C/W 1 NUT) 
UNION ALL
SELECT  STUD BOLT SET, ASME B1.1, ASTM A193 B7, ASME B1.1, ASTM A194 GR 2H, GALVANISED (28 x 1 3/4" UN8 x 270 LG C/W 1 NUT) 
)
SELECT 
SUBSTRING(description, LEN(description) - pos1 - pos2, pos2 - 1)
FROM MyTable
/* REVERSE the string so that searching for the rightmost character/pattern will be equivalent to searching the leftmost character/reversed pattern in the reversed string */
CROSS APPLY (SELECT REVERSE(description)) AS rev(revDescription) 
/* Find the rightmost occurrence of  LG , by searching the leftmost occurrence of  GL  in the reserved string */
CROSS APPLY (SELECT patindex(REVERSE(N % % LG% ), revDescription)) AS ca1(pos1)
/* Skipping the L (from LG) and its preceding space (i.e. starting on character 3), find the rightmost space */
CROSS APPLY (SELECT CHARINDEX(   , SUBSTRING(revDescription, pos1 + 3, 1000))) AS ca2(pos2)

其他数据库可能更能支持定期的表述,使查询更加容易撰写。 下文是Pogres的例子,我们能够在1行中做到这一点;类似做法也可能与其他数据库合作。

WITH MyTable(description) AS (
SELECT  STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 140 LG C/W 1 NUT, 12 X M24 X 170 LG C/W 1 NUT) 
UNION ALL
SELECT  STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (2 X M20 X 80 LG C/W 1 NUT, 6 X M20 X 90 LG C/W 1 NUT) 
UNION ALL
SELECT  STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 130 LG C/W 1 NUT, 12 X M24 X 150 LG C/W 1 NUT) 
UNION ALL
SELECT  STUD BOLT SET, ASME B1.1, ASTM A193 B7, ASME B1.1, ASTM A194 GR 2H, GALVANISED (28 x 1 3/4" UN8 x 270 LG C/W 1 NUT) 
)
SELECT UNNEST(regexp_matches(description,  (d+)s*LG(?!LG) ))
FROM MyTable

In this case, we capture the number ((d+)) before LG. (?!LG) is a negative lookahead, which means there cannot be allowed another occurrence of LG to the right of the one we want to capture.
If you were to remove (?!LG) (as well as the UNNEST), you would get all the numbers immediately preceding all the occurrences of LG in 1 array per input string.

请尝试以下解决办法:通过XML和XQuery标/>。

从扼杀结束起,预期的价值始终处于相同地位。

我们正在通过XPath的定点/root/r[last() - 4]

<>SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (id INT IDENTITY PRIMARY KEY, tokens NVARCHAR(1024));
INSERT INTO @tbl (tokens) VALUES
( STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 140 LG C/W 1 NUT, 12 X M24 X 170 LG C/W 1 NUT) ),
( STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (2 X M20 X 80 LG C/W 1 NUT, 6 X M20 X 90 LG C/W 1 NUT) ),
( STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 130 LG C/W 1 NUT, 12 X M24 X 150 LG C/W 1 NUT) ),
( STUD BOLT SET, ASME B1.1, ASTM A193 B7, ASME B1.1, ASTM A194 GR 2H, GALVANISED (28 x 1 3/4" UN8 x 270 LG C/W 1 NUT) );
-- DDL and sample data population, end

DECLARE @separator CHAR(1) = SPACE(1);

SELECT *
    , bolt_length = c.value( (/root/r[last() - 4]/text())[1] ,  INT )
FROM @tbl AS t
CROSS APPLY (SELECT TRY_CAST( <root><r><![CDATA[  + 
    REPLACE(tokens, @separator,  ]]></r><r><![CDATA[ ) + 
     ]]></r></root>  AS XML)) AS t1(c);

<><>Output

id tokens bolt_length
1 STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 140 LG C/W 1 NUT, 12 X M24 X 170 LG C/W 1 NUT) 170
2 STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (2 X M20 X 80 LG C/W 1 NUT, 6 X M20 X 90 LG C/W 1 NUT) 90
3 STUD BOLT SET, SANS 1700, GR 8.8, SANS 1700, GR 8, GALVANISED (8 X M24 X 130 LG C/W 1 NUT, 12 X M24 X 150 LG C/W 1 NUT) 150
4 STUD BOLT SET, ASME B1.1, ASTM A193 B7, ASME B1.1, ASTM A194 GR 2H, GALVANISED (28 x 1 3/4" UN8 x 270 LG C/W 1 NUT) 270




相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

难以执行 REGEXP_SUBSTR

I m 查询Oracle 10g。 我有两张表格(样本数据见下文)。 i m 试图提取一些领域

SQL Query Shortcuts

What are some cool SQL shorthands that you know of? For example, something I learned today is you can specify to group by an index: SELECT col1, col2 FROM table GROUP BY 2 This will group by col2

PHP array callback functions for cleaning output

I have an array of output from a database. I am wondering what the cleanest way to filter the values is example array Array ( [0] => Array ( [title] => title 1 ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

Running numbers in SQL

I have a SQL-statement like this: SELECT name FROM users WHERE deleted = 0; How can i create a result set with a running number in the first row? So the result would look like this: 1 Name_1 2 ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签