extract number from a string sql - sql

I have this SQL Data:
AT_SendMail_v1
AT_Certificate_v10
AT_Certificate_v100
And I want this output:
AT_SendMail_v2
AT_Certificate_v11
AT_Certificate_v101
I have this code but it doesn't work for the numbers that they more than 19:
SELECT CASE
WHEN ISNUMERIC(RIGHT([internalname],1)) = 1
THEN LEFT([internalname],LEN([internalname])-1) + cast((CONVERT(INT, RIGHT([internalname],1)) + 1) as varchar(100))
ELSE [internalname] + '_v1'
END
,[id]
FROM [task]
thanks :)

Assuming that the number is always the end of the string:
using patindex():
select
name
, new_name = case when patindex('%[_]v[1234567890]%',name) > 0
then left(name,(patindex('%[_]v[1234567890]%',name)+1))
+ convert(varchar(10),convert(int
,right(name,len(name)-(patindex('%[_]v[1234567890]%',name)+1)))
+1)
else name+'_v1'
end
from task
rextester demo: http://rextester.com/AWPXB86451
returns:
+----------------------+----------------------+
| name | new_name |
+----------------------+----------------------+
| AT_SendMail_v1 | AT_SendMail_v2 |
| AT_Certificate_v10 | AT_Certificate_v11 |
| AT_Certificate_v_v50 | AT_Certificate_v_v51 |
+----------------------+----------------------+

You could use SUBSTRING to get number after _v, after it check If It is numeric using ISNUMERIC, after It increase that number by 1, convert It to string and concat string.
DECLARE #internalname NVARCHAR(40)
SET #internalname = 'AT_SendMail_v19'
SELECT
CASE WHEN ISNUMERIC(SUBSTRING(#internalname, CHARINDEX('_v', #internalname) + 2, LEN(#internalname))) = 1
THEN SUBSTRING(#internalname,+2, CHARINDEX('_v',#internalname)) + CAST(SUBSTRING(#internalname, CHARINDEX('_v', #internalname) + 2, LEN(#internalname)) + 1 AS NVARCHAR(60))
ELSE #internalname + '_v1'
END

Try this :
declare #test varchar(50) = 'AT_SendMail_v1';
select Output = case when ISNUMERIC( substring ( #test , charindex('_v',#test)+2 , len(#test)) )=1 then
left (#test , charindex('_v',#test)+1) + cast( cast(substring ( #test , charindex('_v',#test)+2 , len(#test)) as int)+1 as varchar )
else
#test+'_v1' end;
Demo.

Here is one way to increment the numbers, you can then build it into your string...
DECLARE #str NVARCHAR(20) = 'AT_SendMail_v1';
DECLARE #intCharIndex INT = CHARINDEX('_v',#str);
IF(#intCharIndex = 0)
BEGIN
SELECT 'No string found';
END
IF(#intCharIndex > 0)
BEGIN
DECLARE #int INT = LEN(#str) - #intCharIndex - 1;
DECLARE #intVersion INT = RIGHT(#str,#int) + 1;
SELECT LEFT(#str,#intCharIndex) + 'v' + RTRIM(CAST(#intVersion AS NVARCHAR(4)));
END

that was the best code for me, thanks :)
SELECT
CASE
WHEN CHARINDEX('_v', [internalname], 1) <> 0 THEN LEFT([internalname], CHARINDEX('_v', [internalname], 1) + 1) + CAST(CAST(RIGHT([internalname], LEN([internalname]) - CHARINDEX('_v', [internalname], 1) - 1) AS INT) + 1 AS VARCHAR(100))
ELSE [internalname] + '_v1'
END
,[id]
FROM [task]

How about this that caters for ANY number after the _v
Select Left(internalName, Len(internalName) - CharIndex('v_', Reverse(internalName)) + 1) + Cast((Cast((Right(internalName, CharIndex('v_', Reverse(internalName)) -1)) As Integer) + 1) As NVarchar(32))
From task

Related

Year number range formatting

I have these year number ranges
1993-1997
1923-1935
1998-2015
I'm trying to produce this shortened version of these year ranges.
1993-7
1923-35
1998-2015
So far my query looks like this. But its not working on the 2nd and 3rd samples, 1923-1935, and 1998-2015.
declare #bookyear varchar(50)
declare #year1 char(4)
declare #year2 char(4)
set #bookyear = '1993-1997'
set #year1 = substring(#bookyear, 1, charindex('-', #bookyear)-1)
set #year2 = substring(#bookyear, charindex('-', #bookyear) + 1, len(#bookyear))
select cast(#year1 as varchar(50)) + '-'+ substring(#year2, 4, 1)
Note: Year is always in 4 digits.
I am assuming you want a single digit year if its within the same decade, and double digit year when its a different decade. In which case use a case statement to compare the decade component and then display the appropriate number of digits e.g.
declare #bookyear varchar(50), #year1 char(4), #year2 char(4);
set #bookyear = '1993-1997';
set #year1 = substring(#bookyear, 1, charindex('-', #bookyear)-1);
set #year2 = substring(#bookyear, charindex('-', #bookyear) + 1, len(#bookyear));
select cast(#year1 as varchar(50)) + '-'
+ case when substring(#Year1,1,3) = substring(#Year2,1,3) then substring(#year2, 4, 1)
when substring(#Year1,1,2) = substring(#Year2,1,2) then substring(#year2, 3, 2)
else substring(#year2, 1, 4) end;
Assuming your input strings will always have same length i.e. 9 characters
drop table if exists t
create table t (d varchar(9))
insert into t values
('1993-1997')
,('1923-1935')
,('1998-2015')
,('2095-2115')
SQLFIDDLE
select d
, case
when LEFT(d, 3) = LEFT(RIGHT(d , 4), 3) then LEFT(d, 5) + RIGHT(d, 1)
when LEFT(d, 2) = LEFT(RIGHT(d , 4), 2) then LEFT(d, 5) + RIGHT(d, 2)
when LEFT(d, 1) = LEFT(RIGHT(d , 4), 1) then LEFT(d, 5) + RIGHT(d, 3)
ELSE d
end
FROM t
There are actually 2 ways to address this.
Looking for the same from the right.
Or looking for differences from the left.
Example snippet:
declare #bookyear varchar(9);
set #bookyear = '1993-1997';
--
-- looking for different digits from left to right
--
set #bookyear = left(#bookyear,5) +
case
when left(#bookyear,1) != substring(#bookyear,6,1) then right(#bookyear,4)
when left(#bookyear,2) != substring(#bookyear,6,2) then right(#bookyear,3)
when left(#bookyear,3) != substring(#bookyear,6,3) then right(#bookyear,2)
else right(#bookyear,1)
end;
select #bookyear as bookyear1;
-- reset variable
set #bookyear = '1993-1997';
--
-- looking for same digits from right to left
--
set #bookyear = left(#bookyear,5) +
case
when left(#bookyear,3) = substring(#bookyear,6,3) then substring(#bookyear,9,1)
when left(#bookyear,2) = substring(#bookyear,6,2) then substring(#bookyear,8,2)
when left(#bookyear,1) = substring(#bookyear,6,1) then substring(#bookyear,7,3)
else substring(#bookyear,6,4)
end;
select #bookyear as bookyear2;
A test snippet using a table variable:
declare #Test table (bookyear varchar(9));
insert into #Test (bookyear) values
('1993-1997'),
('1923-1935'),
('1998-2015'),
('2095-2115');
select
bookyear,
left(bookyear,5) +
case
when left(bookyear,1) != substring(bookyear,6,1) then right(bookyear,4)
when left(bookyear,2) != substring(bookyear,6,2) then right(bookyear,3)
when left(bookyear,3) != substring(bookyear,6,3) then right(bookyear,2)
else right(bookyear,1)
end as bookyear1,
left(bookyear,5) +
case
when left(bookyear,3) = substring(bookyear,6,3) then substring(bookyear,9,1)
when left(bookyear,2) = substring(bookyear,6,2) then substring(bookyear,8,2)
when left(bookyear,1) = substring(bookyear,6,1) then substring(bookyear,7,3)
else substring(bookyear,6,4)
end as bookyear2
from #Test;
Returns:
bookyear bookyear1 bookyear2
1993-1997 1993-7 1993-7
1923-1935 1923-35 1923-35
1998-2015 1998-2015 1998-2015
2095-2115 2095-115 2095-115
A test on rextester here

select a condition as column in sql

As we can have a command like this in C# or Java
return 1 < 2;
Is it possible to do something like that in SQL?
SELECT 1 < 2
or in my case:
Select
Case when sign = '<' then col1 < 10 else col1 > 10 end
from ...
Result: 0
When I use SELECT 1 < 2 I get an error:
Msg 102, Level 15, State 1, Line 1 Incorrect syntax near '<'.
So it seems that there is a problem with this statement. I'm using TSQL.
I don't know what DBMS you are using, I am using T-SQL in this example. This should work:
declare #col1 int
declare #sign varchar(1)
set #col1 = 10
set #sign = '<'
Select
case when (#sign = '<') and (#col1 < 10) then 1
when (#sign = '>') and (#col1 > 10) then 1
else 0
end
I think you mean this:
DECLARE #Col1 INT = 10; --Set your value
SELECT Result = CASE WHEN #Col1 > 10 THEN CAST(#Col1 AS VARCHAR(10) ) + ' > 10'
WHEN #Col1 < 10 THEN CAST(#Col1 AS VARCHAR(10) ) + ' < 10'
ELSE CAST(#Col1 AS VARCHAR(10) ) + ' = 10'
END
OR
DECLARE #Col1 INT = 10;
DECLARE #VarForCompare INT = 55;
SELECT Result = CASE WHEN #Col1 > #VarForCompare THEN CAST(#Col1 AS VARCHAR(10) ) + ' > ' + CAST(#VarForCompare AS VARCHAR(10) )
WHEN #Col1 < #VarForCompare THEN CAST(#Col1 AS VARCHAR(10) ) + ' < ' + + CAST(#VarForCompare AS VARCHAR(10) )
ELSE CAST(#Col1 AS VARCHAR(10) ) + ' = ' + + CAST(#VarForCompare AS VARCHAR(10) )
END
OR using IF:
IF #Col1 > #VarForCompare
SELECT CAST(#Col1 AS VARCHAR(10) ) + ' > ' + CAST(#VarForCompare AS VARCHAR(10) ) Result
ELSE
IF #Col1 < #VarForCompare
SELECT CAST(#Col1 AS VARCHAR(10) ) + ' < ' + CAST(#VarForCompare AS VARCHAR(10) ) Result
ELSE
SELECT CAST(#Col1 AS VARCHAR(10) ) + ' = ' + CAST(#VarForCompare AS VARCHAR(10) ) Result
I don't see why you need Sign variable.
select case when 1 <2 then 'true' else 'false' end
You could also use the inline if statement instead of CASE:
SELECT IIF(1 < 2,'true','false')

MSSQL - Create table function, return substring

I need to create this table function. The function needs to return single words from passed parameters like: hello, hhuu, value
The table function should return:
hello,
hhuu,
value
But I am always getting some errors, please could you help me?
you can write as:
DECLARE #input_char VARCHAR(255)
SET #input_char = 'hello, hhuu, value'
;WITH cte AS (
SELECT
CAST('<r>' + REPLACE(#input_char, ' ', '</r><r>') + '</r>' AS XML) AS input_char
)
SELECT
rtrim( LTRIM (xTable.xColumn.value('.', 'VARCHAR(MAX)')) ) AS input_char
FROM cte
CROSS APPLY input_char.nodes('//r') AS xTable(xColumn)
Please give a look at this article:
http://www.codeproject.com/Tips/625872/Convert-a-CSV-delimited-string-to-table-column-in
and you could use ' ' (space) as delimiter.
SELECT * FROM dbo.CSVtoTable('hello, hhuu, value', ' ')
I have used the following function many times. It is a bit lengthy forgive me, but it has become a great tool for me.
CREATE Function [dbo].[ParseText2Table]
(
#p_SourceText varchar(MAX)
,#p_Delimeter varchar(100) = ',' --default to comma delimited.
)
RETURNS #retTable TABLE
(
POSITION INT
,Int_Value bigint
,Num_value REAL--Numeric(18,3)
,txt_value varchar(MAX)
)
AS
BEGIN
DECLARE #tmpTable TABLE
(
Position2 INT IDENTITY(1,1) PRIMARY KEY
,Int_Value bigint
,Num_value REAL--Numeric(18,3)
,txt_value varchar(MAX)
)
DECLARE #w_Continue INT
,#w_StartPos INT
,#w_Length INT
,#w_Delimeter_pos INT
,#w_tmp_int bigint
,#w_tmp_num REAL--numeric(18,3)
,#w_tmp_txt varchar(MAX)
,#w_Delimeter_Len INT
IF len(#p_SourceText) = 0
BEGIN
SET #w_Continue = 0 -- force early exit
END
ELSE
BEGIN
-- if delimiter is ' ' change
IF #p_Delimeter = ' '
BEGIN
SET #p_SourceText = replace(#p_SourceText,' ','ÿ')
SET #p_Delimeter = 'ÿ'
END
-- parse the original #p_SourceText array into a temp table
SET #w_Continue = 1
SET #w_StartPos = 1
SET #p_SourceText = RTRIM( LTRIM( #p_SourceText))
SET #w_Length = DATALENGTH( RTRIM( LTRIM( #p_SourceText)))
SET #w_Delimeter_Len = len(#p_Delimeter)
END
WHILE #w_Continue = 1
BEGIN
SET #w_Delimeter_pos = CHARINDEX( #p_Delimeter
,(SUBSTRING( #p_SourceText, #w_StartPos
,((#w_Length - #w_StartPos) + #w_Delimeter_Len)))
)
IF #w_Delimeter_pos > 0 -- delimeter(s) found, get the value
BEGIN
SET #w_tmp_txt = LTRIM(RTRIM( SUBSTRING( #p_SourceText, #w_StartPos
,(#w_Delimeter_pos - 1)) ))
IF dbo.isReallyNumeric(#w_tmp_txt) = 1 --and not #w_tmp_txt in('.', '-', '+', '^')
BEGIN
--set #w_tmp_int = cast( cast(#w_tmp_txt as real) as bigint)--numeric) as bigint)
SET #w_tmp_int = CASE WHEN (CAST(#w_tmp_txt AS REAL) BETWEEN -9223372036854775808 AND 9223372036854775808) THEN CAST( CAST(#w_tmp_txt AS REAL) AS bigint) ELSE NULL END
SET #w_tmp_num = CAST( #w_tmp_txt AS REAL)--numeric(18,3))
END
ELSE
BEGIN
SET #w_tmp_int = NULL
SET #w_tmp_num = NULL
END
SET #w_StartPos = #w_Delimeter_pos + #w_StartPos + (#w_Delimeter_Len- 1)
END
ELSE -- No more delimeters, get last value
BEGIN
SET #w_tmp_txt = LTRIM(RTRIM( SUBSTRING( #p_SourceText, #w_StartPos
,((#w_Length - #w_StartPos) + #w_Delimeter_Len)) ))
IF dbo.isReallyNumeric(#w_tmp_txt) = 1 --and not #w_tmp_txt in('.', '-', '+', '^')
BEGIN
--set #w_tmp_int = cast( cast(#w_tmp_txt as real) as bigint)--as numeric) as bigint)
SET #w_tmp_int = CASE WHEN (CAST(#w_tmp_txt AS REAL) BETWEEN -9223372036854775808 AND 9223372036854775808) THEN CAST( CAST(#w_tmp_txt AS REAL) AS bigint) ELSE NULL end
SET #w_tmp_num = CAST( #w_tmp_txt AS REAL)--numeric(18,3))
END
ELSE
BEGIN
SET #w_tmp_int = NULL
SET #w_tmp_num = NULL
END
SELECT #w_Continue = 0
END
INSERT INTO #tmpTable VALUES( #w_tmp_int, #w_tmp_num, #w_tmp_txt )
END
INSERT INTO #retTable SELECT Position2, Int_Value ,Num_value ,txt_value FROM #tmpTable
RETURN
END
Here are the supporting functions for above as well:
CREATE FUNCTION dbo.isReallyInteger
(
#num VARCHAR(64)
)
RETURNS BIT
BEGIN
IF LEFT(#num, 1) = '-'
SET #num = SUBSTRING(#num, 2, LEN(#num))
RETURN CASE
WHEN PATINDEX('%[^0-9-]%', #num) = 0
AND CHARINDEX('-', #num) <= 1
AND #num NOT IN ('.', '-', '+', '^')
AND LEN(#num)>0
AND #num NOT LIKE '%-%'
THEN
1
ELSE
0
END
END
CREATE FUNCTION dbo.isReallyNumeric
(
#num VARCHAR(64)
)
RETURNS BIT
BEGIN
IF LEFT(#num, 1) = '-'
SET #num = SUBSTRING(#num, 2, LEN(#num))
DECLARE #pos TINYINT
SET #pos = 1 + LEN(#num) - CHARINDEX('.', REVERSE(#num))
RETURN CASE
WHEN PATINDEX('%[^0-9.-]%', #num) = 0
AND #num NOT IN ('.', '-', '+', '^')
AND LEN(#num)>0
AND #num NOT LIKE '%-%'
AND
(
((#pos = LEN(#num)+1)
OR #pos = CHARINDEX('.', #num))
)
THEN
1
ELSE
0
END
END
Usage Examples:
--Single Character Delimiter
--select * from dbo.ParseText2Table('100|120|130.56|Yes|Cobalt|Blue','|')
--select txt_value from dbo.ParseText2Table('100 120 130.56 Yes Cobalt Blue',' ') where Position = 3
--select * from dbo.ParseText2Table('100,120,130.56,Yes,Cobalt,Blue,,',',')
/*
POSITION Int_Value Num_value txt_value
----------- ----------- -------------------- --------------
1 100 100.000 100
2 120 120.000 120
3 131 130.560 130.56
4 NULL NULL Yes
5 NULL NULL Cobalt Blue
*/

Have someone a function for SQL Server that given a pattern and a value could return a normalized value

I'm programming a function in SQL 2008R2 that i could give it some parameters like a value varchar, a pattern varchar, a separator char and a filler also char. Then I would like to give the value '22687' with the patter '000.000.000.000', a separator '.' and the filler would be '0', then i would like to expect the function will return '000.000.022.687', does any one have a function already done that can do this?
Something like this:
DECLARE #valor VARCHAR(30)
DECLARE #formato VARCHAR(30)
DECLARE #separador CHAR(1)
DECLARE #rellenarcon CHAR(1)
SELECT #valor = '22959'
SELECT #formato = '000.000.000.000'
SELECT #separador = '.'
SELECT #rellenarcon = '0'
DECLARE #n INTEGER
DECLARE #m INTEGER
DECLARE #i INTEGER
DECLARE #j INTEGER
SELECT #n = LEN(#formato)
SELECT #m = LEN(#valor)
SELECT #i = 1
SELECT #j = 1
DECLARE #res2 varchar(30)
SELECT #res2 = ''
SELECT #valor = REVERSE(#valor)
WHILE #i<=#n
BEGIN
if SUBSTRING(#formato,#i,1) <> #separador
begin
IF #j<=#m
BEGIN
SELECT #res2 = #res2 + SUBSTRING(#valor,#j,1)
SELECT #i=#i+1
SELECT #j=#j+1
END
ELSE
BEGIN
SELECT #res2 = #res2 + #rellenarcon
SELECT #i=#i+1
END
end
else
BEGIN
SELECT #res2 = #res2 + #separador
SELECT #i=#i+1
END
END
print reverse(#res2)
Is a crossover code from java to tsql, the original code in java is:
public static String formatear(String valor, String formato, char separator,
char fillWith, Map<Integer, String> params) {
int n = formato.length() - 1;
int m = valor.length() - 1;
int i = n;
int j = m;
StringBuilder res = new StringBuilder(formato);
for(; i >= 0; i--) {
if(res.charAt(i) != separator) {
if(j >= 0) {
res.deleteCharAt(i);
res.insert(i, valor.charAt(j--));
} else {
res.deleteCharAt(i);
res.insert(i, fillWith);
}
}
}
if(params != null) {
Set<Integer> keys = params.keySet();
for(Integer key : keys) {
i = key;
res.deleteCharAt(i);
res.insert(i, params.get(key));
}
}
return res.toString();
}
The following assumes well-formed inputs, e.g. the value is not longer than the pattern.
declare #Pattern as VarChar(64) = '000.000.000.000';
declare #Fill as Char = '0';
declare #Value as VarChar(64) = '22687';
declare #False as Bit = 0;
declare #True as Bit = 1;
with Gargoyle as (
select #Pattern as Pattern, #Value as Value, Cast( '' as VarChar(64) ) as Buffer,
case when Right( #Pattern, 1 ) = #Fill then #True else #False end as Fill
union all
select
-- Always consume a character from the pattern.
Left( Pattern, Len( Pattern ) - 1 ),
-- Consume a character from the value if the pattern contains fill at the current position.
case
when Fill = #True and Value != '' then Left( Value, Len( Value ) - 1 )
else Value end,
-- Add the correct character to the buffer.
Cast( case when Fill = #True and Value != '' then Right( Value, 1 ) else Right( Pattern, 1 ) end + Buffer as VarChar(64) ),
-- Check the next pattern character for fill.
case
when Len( Pattern ) = 1 then #False
when Substring( Pattern, Len( Pattern ) - 1, 1 ) = #Fill then #True
else #False end
from Gargoyle
where Pattern != ''
)
select Buffer
from Gargoyle
where Pattern = '';
Or, as a function:
create function dbo.PatternFill( #Pattern as VarChar(64), #Fill as Char, #Value as VarChar(64) )
returns VarChar(64)
as
begin
declare #Buffer as VarChar(64) = ''
declare #PatternChar as Char = Right( #Pattern, 1 )
declare #ValueChar as Char = Right( #Value, 1 )
while #Pattern != ''
begin
if #PatternChar = #Fill and #ValueChar != ''
begin
-- Replace a fill character with a value character.
select #Buffer = #ValueChar + #Buffer
if Len( #Value ) > 1
select #Value = Left( #Value, Len( #Value ) - 1 ), #ValueChar = Right( #Value, 1 )
else
select #ValueChar = '', #Value = ''
end
else
begin
-- Copy the pattern character.
select #Buffer = #PatternChar + #Buffer
end
if Len( #Pattern ) > 1
select #Pattern = Left( #Pattern, Len( #Pattern ) - 1 ), #PatternChar = Right( #Pattern, 1 )
else
select #PatternChar = '', #Pattern = ''
end
return #Buffer
end
go
declare #Result as VarChar(64)
declare #Count as Int = 1000000
declare #Start as DateTime = GetDate()
while #Count > 0
select #Result = dbo.PatternFill( '000.000.000.000', '0', '22687' ), #Count = #Count - 1
select #Result as [Result], DateDiff( ms, #Start, GetDate() ) as [Total ms]
1,000,000 iterations on my notebook took 151,656ms, but it's busy BOINCing. That's simple timing with no correction for the time consumed by an empty loop or calling an empty function.
This query will do it:
;with cteZeroPadded(Num) as
(
Select Right('000000000000' + '22687', 12)
)
,cteSplit as
(
Select SUBSTRING(Num, 1, 3) Col1
,SUBSTRING(Num, 4, 3) Col2
,SUBSTRING(Num, 7, 3) Col3
,SUBSTRING(Num, 10, 3) Col4
From cteZeroPadded
)
Select Col1 + '.' + Col2 + '.' + Col3 + '.' + Col4
From cteSplit
In SQLServer2005+ you can use option with recursive CTE
DECLARE #valor varchar(30) = '22959',
#formato varchar(30) = '000000000000000',
#text varchar(30),
#result varchar(30) = N''
SET #text = REVERSE(RIGHT(#formato + #valor, 15))
;WITH cte AS
(
SELECT 1 AS Number, SUBSTRING(#text, 1, 1) AS Num
UNION ALL
SELECT c.Number + 1,
CASE WHEN c.Number IN(3, 7, 11) THEN '.' ELSE
SUBSTRING(#text, CASE WHEN c.Number > 11 THEN c.Number - 2
WHEN c.Number > 7 THEN c.Number - 1
WHEN c.Number > 3 THEN c.Number
ELSE c.Number + 1
END, 1)
END
FROM cte c
WHERE Number < LEN(#text)
)
SELECT #result += c.Num
FROM cte c
ORDER BY Number DESC
SELECT #result
See demo on SQLFiddle

How to extract dates from a varchar string

How to extract dates from a varchar string;
Format of data:
Rates from 16th April 2011 to 31st Aug 2011
I want output as '16/04/2011' and '31/08/2011'
Regards,
Nitin
To do not play with day end part like "d","st" etc, it is better to split your string into words and then analyse it. Double spaces being removed at the beginning.
DECLARE #s NVARCHAR(MAX)= 'Rates from 16th April 2011 to 2st Aug 2011'
SET #s = REPLACE(#s, ' ', ' ')
DECLARE #BegDay VARCHAR(2)= '' ,
#begMonth NVARCHAR(100) ,
#BegYear VARCHAR(4)
DECLARE #EndDay VARCHAR(2) ,
#EndMonth NVARCHAR(100) ,
#EndYear VARCHAR(4)
DECLARE #BegDate DATETIME ,
#EndDate DATETIME
DECLARE #Words TABLE
(
Word NVARCHAR(1000) ,
WordNr INT
) ;
WITH c ( Char, Pos, WordNr )
AS ( SELECT SUBSTRING(#s, 1, 1) CHAR ,
1 ,
CAST(0 AS BIGINT)
UNION ALL
SELECT SUBSTRING(#s, pos + 1, 1) CHAR ,
pos + 1 ,
CASE WHEN SUBSTRING(#s, pos + 1, 1) = SPACE(1)
THEN c.WordNr + 1
ELSE c.WordNr
END
FROM c
WHERE pos < LEN(#s)
)
INSERT INTO #Words
( Word ,
WordNr
)
SELECT RTRIM(LTRIM(SUBSTRING(#s, c.Pos,
ISNULL(c2.Pos, LEN(#s)) - c.Pos + 1))) ,
c.WordNr + 1
FROM ( SELECT *
FROM c
) c
LEFT OUTER JOIN C C2 ON c2.WordNr = c.WordNr + 1
AND c2.Char = ' '
WHERE c.char = ' '
OR c.Pos = 1 ;
WITH c ( Word, [CHAR], Pos )
AS ( SELECT T.Word ,
CAST(SUBSTRING(T.Word, 1, 1) AS NVARCHAR(100)) ,
1
FROM #Words T
WHERE WordNr = 3
UNION ALL
SELECT c.Word ,
CAST(SUBSTRING(c.Word, 1, pos + 1) AS NVARCHAR(100)) ,
pos + 1
FROM c
WHERE ISNUMERIC(SUBSTRING(C.Word, c.pos + 1, 1)) = 1
)
SELECT TOP 1
#BegDay = char
FROM c
ORDER BY pos DESC
SET #begMonth = ( SELECT T.Word
FROM #Words T
WHERE T.WordNr = 4
)
SET #BegYear = ( SELECT T.Word
FROM #Words T
WHERE T.WordNr = 5
)
SET #BegDate = #BegDay + '' + #begMonth + #Begyear ;
WITH c ( Word, [CHAR], Pos )
AS ( SELECT T.Word ,
CAST(SUBSTRING(T.Word, 1, 1) AS NVARCHAR(100)) ,
1
FROM #Words T
WHERE WordNr = 7
UNION ALL
SELECT c.Word ,
CAST(SUBSTRING(c.Word, 1, pos + 1) AS NVARCHAR(100)) ,
pos + 1
FROM c
WHERE ISNUMERIC(SUBSTRING(C.Word, c.pos + 1, 1)) = 1
)
SELECT TOP 1
#EndDay = char
FROM c
ORDER BY pos DESC
SET #EndMonth = ( SELECT T.Word
FROM #Words T
WHERE T.WordNr = 8
)
SET #EndYear = ( SELECT T.Word
FROM #Words T
WHERE T.WordNr = 9
)
SET #EndDate = #EndDay + '' + #EndMonth + #Endyear
SELECT #BegDate Begindate ,
#EndDate EndDate