Reputation: 2413
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?
Upvotes: 1
Views: 807
Reputation: 280252
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
Upvotes: 3
Reputation: 2413
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.
Upvotes: 0