Pet*_*ete 5 t-sql sql-server-2012
我希望从一个字段中检索信息,但无法准确获取我想要的信息。我想要的信息没有固定顺序,我也在寻找两种不同的东西。这是我正在使用的信息的示例。
|PEvent| PDate | PDescription |
| 3 | 2014-11-21 | Padding, 90 Series, Stage, SF550 |
| 4 | 2014-11-21 | Padding, 45 Series, 144 Stage SF90, 15 spor, AR |
| 5 | 2013-03-06 | 400 Series, 96 STAGE RE FLEX 30 |
| 6 | 2015-01-09 | Padding, 20 Series, 13 Stage SF 550, Housing |
Run Code Online (Sandbox Code Playgroud)
我想要的是 SF 和数字以及 FLEX 和它后面的数字,在这些情况下是 SF550、SF90、SF 550 FLEX 30。我也想得到 FLEX 和它后面的数字。我遇到的问题是数据中有很多差异。我不能说左边有 10 个空格,因为它并不总是 10 个空格。我从右边也有同样的问题。我遇到的另一个问题是,有时 SF 和 FLEX 与数字正好相反,而有时它们之间会有空格。
我创建了一个 SQL Fiddle 示例数据库,其中包含更多用于测试的记录。
已作出以下假设(其中一些可能重复您的描述部分):
SF
/FLEX
后面总是紧跟一个数字或一个空格字符,然后是一个数字。
SF
/之前总是有一个空格字符FLEX
,除非该项位于字符串的开头。
SF
/后面的数字后面总是有一个逗号或一个空格FLEX
,除非该项目位于字符串的末尾。
考虑到这些,这是我的方法:
SELECT
t.*,
Item = LEFT(item.S, CHARINDEX(' ', item.S + ' ', LEN(prefix.S) + spaces.N + 1))
FROM
dbo.testdesc AS t
CROSS JOIN (VALUES ('SF'), ('FLEX')) AS prefix (S)
CROSS JOIN (VALUES (0), (1)) AS spaces (N)
CROSS APPLY (SELECT NULLIF(PATINDEX('% ' + prefix.S + SPACE(spaces.N) + '[0-9]%', ' ' + t.PDescription), 0)) AS startpos (N)
CROSS APPLY (SELECT CHARINDEX(',', t.PDescription + ',', startpos.N + LEN(prefix.S) + spaces.N)) AS endpos (N)
CROSS APPLY (SELECT SUBSTRING(t.PDescription, startpos.N, endpos.N - startpos.N)) AS item (S)
WHERE
startpos.N IS NOT NULL
;
Run Code Online (Sandbox Code Playgroud)
这是上述查询的输出:
PEvent PDate PDescription Item
------ ----------------------- --------------------------------------------------------- -------
3 2014-11-21 00:00:00.000 Padding, 90 Series, Stage, SF550 SF550
4 2014-11-21 00:00:00.000 Padding, 45 Series, 144 Stage SF90, 15 spor, AR SF90
8 2013-06-14 00:00:00.000 Padding, 900 Series, 140 Stage SF1100, 1/16, Money, TS XB SF1100
10 2014-12-30 00:00:00.000 Padding, 444 Series, 47 Stage SF330, 5/9, house SF330
6 2015-01-09 00:00:00.000 Padding, 20 Series, 13 Stage SF 550, Housing SF 550
5 2013-03-06 00:00:00.000 400 Series, 96 STAGE RE FLEX 30 FLEX 30
7 2013-06-14 00:00:00.000 Padding, FLEX 10 400 Series, 11 Stage, BYHMP FLEX 10
9 2015-02-27 00:00:00.000 Flex 10 40 87 stage Flex 10
Run Code Online (Sandbox Code Playgroud)
为了解释查询使用的一些技巧,它是这样工作的:
原始行集与两个内联视图交叉连接,一个表示所需的前缀 ( prefix
),另一个指定前缀和后续数字之间可能有多少个空格 ( spaces
)。这样,查询将探测所有前缀和分隔空格数(SF
, SF
, FLEX
, FLEX
)的组合。
的PDescription
字符串中搜索的每个组合,一个一个之后,计算出前缀的起始位置。它使用PATINDEX,它为每个前缀和空格编号构建自己的搜索模式。根据上述假设,PATINDEX 需要前缀前有一个空格,前缀后至少有一个数字,可能还有一个空格。
因此,例如,如果当前前缀是SF
并且它之后的当前预期空格数是 1,则模式将为% SF [0-9]%
。为了确保前缀前有一个空格,在PDescription
.
这个技巧完成了两件事:如果前缀在字符串的开头,它有助于找到前缀,并且它使生成的起始位置准确。后者很重要,因为从技术上讲,返回的位置将不匹配前缀本身,而是匹配前面的空格。因此,要获得前缀的实际位置,我们需要将结果加 1。但是,因为我们在源的开头添加了一个空格,所以所有位置都已经向前移动了。所以,最后,结果正好指向前缀的开头。
最后一点是,如果返回的位置为 0,则由NULLIF将其转换为 NULL 。这有助于避免稍后传递给 SUBSTRING 的负长度值的错误。
然后在CHARINDEX 中使用找到的位置来查找该PDescription
位置之后 found 中的第一个逗号。同样,以确保有是一个逗号,字符被追加到PDescription
。结果构成了所寻求项目的结束位置。
使用获得的开始和结束位置,PDescription
使用SUBSTRING函数提取项目。
最后,在 SELECT 子句中,在实际返回项目之前,查询还会检查数字后面是否有空格,以防万一项目没有用逗号正确分隔。通过向项目附加一个空格,它使用与搜索逗号位置相同的技巧,同时考虑前缀的长度和前缀后的预期空格数,以确保找到的空格字符将是一个经过数。
如果在字符串中找不到前缀,则Item
返回 NULL。但是,WHERE 子句将此类行从输出中排除,该子句指定起始位置不为 NULL。
我不确定上面的描述是否足够清楚,但希望它能与代码本身一起帮助。
归档时间: |
|
查看次数: |
3513 次 |
最近记录: |