Вопрос

I have a varchar column in a SQL Server 2005 table that looks like the following:

Mainly Sunny, 13.7°C
Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h

My goal is to parse out the temperature values, 13.7 and 12 respectively. Is there a series of string functions that can be used to locate and retrieve the first word in each string that contains °C?

Это было полезно?

Решение

DECLARE @t TABLE(s VARCHAR(255));

INSERT @t SELECT 'Mainly Sunny, 13.7°C'
UNION ALL SELECT 'Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h';

SELECT RIGHT(LEFT(s, CHARINDEX('°', s)-1), 
  CHARINDEX(' ', REVERSE(LEFT(s, CHARINDEX('°', s)-1)))-1) FROM @t;

So, as a computed column:

DECLARE @t TABLE
(
  s VARCHAR(255), 
  x AS CONVERT(VARCHAR(255),RIGHT(LEFT(s, CHARINDEX('°', s)-1), 
    CHARINDEX(' ', REVERSE(LEFT(s, CHARINDEX('°', s)-1)))-1)) PERSISTED
);

INSERT @t SELECT 'Mainly Sunny, 13.7°C'
UNION ALL SELECT 'Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h';

SELECT s,x FROM @t;

Results:

Mainly Sunny, 13.7°C                                  13.7
Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h     12

If you might have strings that don't contain a ° symbol, then:

DECLARE @t TABLE
(
  s VARCHAR(255), 
  x AS CONVERT(VARCHAR(255), CASE WHEN CHARINDEX('°', s) > 0 THEN 
    RIGHT(LEFT(s, CHARINDEX('°', s)-1), 
    CHARINDEX(' ', REVERSE(LEFT(s, CHARINDEX('°', s)-1)))-1) END) PERSISTED
);

INSERT @t SELECT 'Mainly Sunny, 13.7°C'
UNION ALL SELECT 'Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h'
UNION ALL SELECT 'No weather to report';

SELECT s,x FROM @t;

Results:

Mainly Sunny, 13.7°C                                  13.7
Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h     12
No weather to report                                  NULL

(If you want something else instead of NULL, I can't imagine what, you can add an ELSE to the CASE expression.)

Also, to prove my solution is flexible without introducing a performance-crippling user-defined function:

DECLARE @SearchString VARCHAR(8000);
SET @SearchString = 'km/h'; -- change this to '°'

DECLARE @t TABLE
(
  s VARCHAR(255)
);

INSERT @t SELECT 'Mainly Sunny, 13.7°C'
UNION ALL SELECT 'Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h'
UNION ALL SELECT 'No weather to report'
UNION ALL SELECT 'Wind 102km/h, 23.5°C, mostly cloudy';

SELECT s, x = CONVERT(VARCHAR(255), CASE WHEN CHARINDEX(@SearchString, s) > 0 THEN 
    RIGHT(LEFT(s, CHARINDEX(@SearchString, s)-1), 
    CHARINDEX(' ', REVERSE(LEFT(s, CHARINDEX(@SearchString, s)-1)))-1) END)
FROM @t;

Results:

Mainly Sunny, 13.7°C                                NULL
Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h   15
No weather to report                                NULL
Wind 102km/h, 23.5°C, mostly cloudy                 102

Другие советы

Thank you @AdamWenger and @AaronBertrand for the great tips and the great answer. In the end, I went with something a bit more flexible. I want to have the ability to find words containing strings other than °C as well.

I ended up using a user defined function to parse out the first occurrence of a word containing a given string. It may be messy, and it's the first real user defined function I've written myself, but here's what I came up with.

CREATE function [dbo].[firstWordContaining] 
(@BigString varchar(max), @SearchString varchar(max))
returns varchar(max)
as
begin

-- Handle when search string is not in the big string
if (charindex(@SearchString,@BigString) = 0)
return null

-- Handle when search string is at the beginning
if (charindex(@SearchString,@BigString) = 1)
return substring(@BigString, 0, charindex(' ',@BigString))

-- Eliminate all words before the identified word
declare @Partial varchar(max)
select @Partial = substring(
@BigString,
charindex(@SearchString, @BigString) - charindex(' ',reverse(left(@BigString,charindex(@SearchString, @BigString)))) + 2, 
len(@BigString))

declare @Final varchar(max)
select @Final = case 

-- Handle when the search string is in the middle of the big string
when (charindex(' ',@Partial) > 0) then left(@Partial, charindex(' ',@Partial))

-- Handle when the search string is at the end of the big string
else @Partial
end

return @Final

end

So, if I do select dbo.firstWordContaining('Mainly Sunny, 13.7°C','°C'), I end up with 13.7°C.

If I do select dbo.firstWordContaining('Partly cloudy, 12°C, Humidity 69%, Wind NE 15km/h','°C'), I end up with 12°C,.

The remaining punctuation is easy enough to strip out.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top