从SQL Server的字符串中获取最大的数字?

时间:2019-11-25 09:01:33

标签: sql sql-server

要将这个问题与其他问题分开:

  • 数字在每个字符串中
  • 有时一个字符串中有多个数字
  • 我只需要最大的钱,而不是年份
  • 欧元符号并非出现在每个数字的前面
  • “税前”并没有出现在每一行中
  • 我无权创建函数

我想要这样的东西

输入:

Finance

€10m - €50m pretax
<€5m pretax
>€100m
€10m - 50m pretax from 2019

输出:

Number

50
5
100
50

我已经尝试过了

select SUBSTRING([Finance], len([Finance])-CHARINDEX('€',REVERSE([Finance]))+2, 4)

但是4并不总是给出正确的长度,并且不适用于€10m - 50m,使用'm'作为另一个索引可能是一个解决方案,但是太复杂了。 还有其他准确而优雅的解决方案吗?

2 个答案:

答案 0 :(得分:2)

SQL Server对于字符串解析不是最佳的。但是您正在寻找的子字符串似乎非常有限。

  • 它们以'm'结尾。
  • 他们有'<''>''€'
  • 它们之间用空格隔开。

这建议拆分字符串并在每个片段上进行一些更基本的处理。对于您的示例数据,这是可行的:

with t as (
      select v.*
      from (values ('€10m - €50m pretax'), ('<€5m pretax'), ('>€100m')) v(str)
     )
select *
from t outer apply
     (select top (1) try_convert(int, replace(replace(replace(replace(s.value, '€', ''), 'm', ''), '<', ''), '>', '')) as num
      from string_split(t.str, ' ') s
      where value like  '%m'
      order by try_convert(int, replace(replace(replace(replace(s.value, '€', ''), 'm', ''), '<', ''), '>', '')) desc
     ) x;

Here是db <>小提琴。

答案 1 :(得分:2)

如果您的Sql Server版本中没有STRING_SPLIT函数?
然后,这是一种“复杂的方法使之简单” 方法以获取最大金额。

它使用递归CTE遍历字符串。
然后从中获得最大金额。

示例片段:

-- Sample data
DECLARE @Table table (
  Id int identity(1,1) primary key,
  [Finance] nvarchar(100)
);
INSERT INTO @Table ([Finance]) VALUES 
  ('€10m - €50m pretext')
 ,('<€5m pretext')
 ,('\>€100m')
 ,('€10m - 50m pretax from 2019 ')
 ,('abc €123m def 456m ghi')
;

;WITH RCTE AS
(
   -- The seed query
   SELECT Id, 
    [Finance] AS Str, 
    0 AS Lvl, 
    CAST(NULL AS INT)  AS Num,
    PATINDEX('%[0-9]%', [Finance]) AS pos1,
    PATINDEX('%[0-9][^0-9]%', [Finance]) AS pos2,
   SUBSTRING([Finance],PATINDEX('%[^0-9][0-9]%', [Finance]),1) AS Prefix
   FROM @Table
   WHERE [Finance] LIKE '%[0-9]m%'

   UNION ALL

   -- Looping through the strings
   SELECT Id, 
    SUBSTRING(Str,pos2+1,len(Str)),
    Lvl+1,
    TRY_CAST(SUBSTRING(Str,pos1,pos2-pos1+1) AS INT),
    PATINDEX('%[0-9]%', SUBSTRING(Str,pos2+1,LEN(Str))),
    PATINDEX('%[0-9][^0-9]%', SUBSTRING(Str,pos2+1,LEN(Str))),
    SUBSTRING(Str,pos1-1,1)
    FROM RCTE
    WHERE Str LIKE '%[0-9]m%'
),
AMOUNTS AS
(
    SELECT Id, 
    MAX(Prefix) AS Prefix,
    MAX(Num) AS MaxAmount
    FROM RCTE
    GROUP BY Id
)
SELECT t.Id, a.MaxAmount, a.Prefix, t.[Finance]
FROM @Table t
LEFT JOIN AMOUNTS a ON a.Id = t.Id
ORDER BY t.Id;

结果:

Id  MaxAmount   Prefix  Finance
1   50          €       €10m - €50m pretext
2   5           €       <€5m pretext
3   100         €       \>€100m
4   50          €       €10m - 50m pretax from 2019 
5   456         €       abc €123m def 456m ghi

在妊娠here上进行的测试

但是我是使用STRING_SPLIT似乎更好。

DECLARE @Table table (
  Id int identity(1,1) primary key,
  [Finance] nvarchar(100)
);

INSERT INTO @Table ([Finance]) VALUES 
  ('€10m - €50m pretext')
 ,('<€5m pretext')
 ,('\>€100m')
 ,('€10.0m - 50m pretax from 2019 ')
 ,('abc €123m def 456m ghi')
 ,('200.5m & 50m')


SELECT t.Id, a.Prefix, a.MaxAmount, t.[Finance]
FROM @Table t 
OUTER APPLY
(
  SELECT MAX(LEFT(str,1)) AS Prefix, MAX(TRY_CAST(STUFF(str,1,1,'') AS FLOAT)) AS MaxAmount
  FROM
  (
    SELECT RIGHT(' '+value, PATINDEX('%[^0-9.]%', REVERSE(' '+value))) AS str
    FROM STRING_SPLIT(t.[Finance], 'm') AS spl
    WHERE value LIKE  '%[0-9]'
  ) q
) AS a

db <>小提琴here

的测试