Convert to valid decimal data type - sql

I have a column [Cash] nvarchar(50) that has data that will later be converted to decimal(9,3) during an import process,some of the data is consistent with normal looking numeric values such as 134.630,-80.662 and 324.372. Occasionally I have data with multiple dots for the numeric values such as 1.324.372 and -2.134.630. Is there a way of removing this extra dot.

declare #yourtable table(cash varchar(20))
insert #yourtable values('1.324.372')
insert #yourtable values('-2.134.630')
insert #yourtable values('1.234.567.89')
Old Code:
select reverse(replace(replace(stuff(reverse(cash), charindex(
'.', reverse(cash)), 1, ','), '.', ''), ',', '.'))
from #yourtable
Slightly upgraded code(result is the same):
select reverse(stuff(reverse(replace(cash, '.', '')),
charindex('.', reverse(cash)), 1, '.'))
from #yourtable
Result:
1324.372
-2134.630
1234567.89

You could;
select case when len(cash) - len(replace(cash, '.', '')) > 1 then
reverse(stuff(reverse(cash), charindex('.', reverse(cash)), 1, ''))
else
cash
end
from T

Create a view that includes a calculated field with the proper value.
That way you can still see the varchar value and the corresponding decimal value.
Something like this:
select
[Cash],
cast(replace([Cash],'.','') as decimal) as [CashDecimal]
from ....

Related

Best way to pad section of this string with 0s

This is 2 examples of what the string currently look like:
6731-121-1
9552-3-1
This is what I want to pad them to look like
0006731-121-1
0009552-003-1
So I want them to be padded with 7 zeroes before the first '-' then 3 zeroes between the first and second '-'
What would be the best way to accomplish this in SQL SELECT statement.
SELECT RIGHT('0000000'
+ ISNULL(
LEFT(OE.exception_id, CHARINDEX('-', OE.exception_id)
- 1) ,
''
) ,7) + '-'
+ SUBSTRING(OE.exception_id, CHARINDEX('-', ( OE.exception_id )), 10) exception_id
ParseName() could be an option here
Example
Declare #YourTable Table ([YourCol] varchar(50))
Insert Into #YourTable Values
('6731-121-1')
,('9552-3-1')
Select *
,NewVal = right('0000000'+parsename(replace(YourCol,'-','.'),3),7)
+'-'
+right('000'+parsename(replace(YourCol,'-','.'),2),3)
+'-'
+parsename(replace(YourCol,'-','.'),1)
From #YourTable
Returns
YourCol NewVal
6731-121-1 0006731-121-1
9552-3-1 0009552-003-1
In situations with more than 3 periods
Example: '1.2.3.4.5'
Or any value is empty
3 examples: '1..3', '1.2.3.', '.2'
Parsename will return null for all values. You will need to split the column using a different method.
Here is an alternative to parsename:
DECLARE #table table(col varchar(100))
INSERT #table values('6731-121-1'),('9552-3-1')
SELECT
col,
REPLICATE('0', 8-x) + STUFF(col, x+1, 0,REPLICATE('0', 4 - (y-x))) newcol
FROM #table
CROSS APPLY
(SELECT CHARINDEX('-', col) x) x
CROSS APPLY
(SELECT CHARINDEX('-', col + '-', x+1) y) y
col newcol
6731-121-1 0006731-121-1
9552-3-1 0009552-003-1

Variable declaration to store multiple values like full column value

I have an requirement where I have to store the column value into an declared variable is it possible anyways. I understand that an variable can store only single value and not multiple values. But in my case I need it badly.
What I have here is to set the column if date value which is in INT has to be converted into Date column and save it in that variable to compare it.
I have some column with values like below
"A(B_CD_EE_FF_DFE)_ERT"
So i have to remove those two bracktes and process.
Set #Variable= (SELECT replace (replace ( replace (SUBSTRING(TXMLFileName, CHARINDEX('(', TXMLFileName)
, CHARINDEX(')',TXMLFileName) - CHARINDEX(')', reverse (TXMLFileName)) ) , ')', '') ,'(' ,'') ,'.xml' , '')
from
tblXML )
Gives me error and below gives answer as I select only top 1.
Set #Variable= (SELECT top 1 replace (replace ( replace (SUBSTRING(TXMLFileName, CHARINDEX('(', TXMLFileName)
, CHARINDEX(')',TXMLFileName) - CHARINDEX(')', reverse (TXMLFileName)) ) , ')', '') ,'(' ,'') ,'.xml' , '')
from
tblXML )
SO is there any known solution... ????? Thanks in advance
A variable needn't just store a single value. You can create e.g. custom table types
CREATE TYPE MyCustomType AS TABLE (
MyCustomTypeId INT,
MyCustomValueColumn VARCHAR(100)
)
Or just declare a comparable table variable inline where needed.
declare #tblXML table (TXMLFileName varchar(50))
insert into #tblXML values
('A(B_CD_EE_FF_DFE)_ERT'),
('(EE_FF_DFE)_ERT'),
('A(B_CD_EE)')
declare #tmp varchar(max)
SET #tmp = ''
SELECT #tmp=#tmp+ replace (replace ( replace (SUBSTRING(TXMLFileName, CHARINDEX('(', TXMLFileName)
, CHARINDEX(')',TXMLFileName) -1 ) , ')', '') ,'(' ,'') ,'.xml' , '')+''' '''
from
#tblXML
select ''''+#tmp
or you don't want to single row use this
SELECT ''''+ replace (replace ( replace (SUBSTRING(TXMLFileName, CHARINDEX('(', TXMLFileName)
, CHARINDEX(')',TXMLFileName) -1 ) , ')', '') ,'(' ,'') ,'.xml' , '')+''''
from
#tblXML

Return a SUBSTRING with a known Prefix and Suffix Character

I have a table that has a Prefix of variable length that always ends with . and a suffix of variable length that always begins with -. The - can also be found in the string of text that I am looking for, so using REVERSE() is likely the best way to identify the suffix -.
ex: Prefix1.ABC-123-Suffix1
I'd like the SUBSTRING() result to look like: ABC-123
I was able to create both a SUBSTRING() to remove the Prefix and a SUBSTRING() to remove the suffix, but I'm having a hard time applying both. The returned text can be variable length.
I'm trying to avoid declaring a variable, but am open to it. I'd prefer to only use SUBSTRING(), REVERSE(), and CHARINDEX() if possible.
This is what I have so far:
SELECT [Col1]
,SUBSTRING((Col1),CHARINDEX('.', (Col1)) + 1, 999) AS [StrippedPrefix]
,REVERSE(SUBSTRING(REVERSE(Col1),CHARINDEX('-', REVERSE(Col1)) + 1, 999)) AS [StrippedSuffix]
--new SUBSTRING() with both Prefix and Suffix stripped
FROM [Table1]
Declare #YourTable table (Col1 varchar(50))
Insert Into #YourTable values
('Prefix1.ABC-123-Suffix1')
Select *
,String=Substring(Col1,charindex('.',Col1)+1,len(Col1)-charindex('.',Col1)-charindex('-',reverse(Col1)))
From #YourTable
Returns
Col1 String
Prefix1.ABC-123-Suffix1 ABC-123
As per M Ali's suggestion (Even better)
Select *
,String=PARSENAME(REPLACE(Col1 , '-', '.') , 3) + '-' + PARSENAME(REPLACE(Col1 , '-', '.') , 2)
From #YourTable
Here the varaiable is only used as demo - should work with your table as well:
DECLARE #s nvarchar(100) = 'Prefix1.ABC-123-Suffix1'
SELECT #s,
SUBSTRING(#s, 1, CHARINDEX('.', #s)-1) StrippedPrefix,
SUBSTRING(#s, LEN(#s)-CHARINDEX('-', REVERSE(#s))+2, CHARINDEX('-', REVERSE(#s))) StrippedSuffix,
SUBSTRING(#s, CHARINDEX('.', #s)+1, LEN(#s)-CHARINDEX('.', #s)-CHARINDEX('-', REVERSE(#s))) NewString
Here is one way
DECLARE #str VARCHAR(100)= 'Prefix1.ABC-123-Suffix'
SELECT Reverse(Stuff(intr_str, 1, Charindex('-', intr_str), ''))
FROM (SELECT Reverse(Stuff(#str, 1, Charindex('.', #str), '')) AS intr_str) a
Result : ABC-123

Selecting between quotes (") in SQL Server 2012

I have a table holding IDs in one column and a string in the second column like below.
COLUMN01 COLUMN02
----------------------------------------------------------------------------------
1 abc"11444,12,13"efg"14,15"hij"16,17,18,19"opqr
2 ahsdhg"21,22,23"ghshds"24,25"fgh"26,27,28,28"shgshsg
3 xvd"3142,32,33"hty"34,35"okli"36,37,38,39"adfd
Now I want to have the following result
COLUMN01 COLUMN02
-----------------------------------------------------------
1 11444,12,13,14,15,16,17,18,19
2 21,22,23,24,25,26,27,28,28
3 3142,32,33,34,35,36,37,38,39
How can I do that?
Thanks so much
Here is one way (maybe not the best, but it seems to work). I am NOT a SQL guru...
First, create this SQL Function. It came from: Extract numbers from a text in SQL Server
create function [dbo].[GetNumbersFromText](#String varchar(2000))
returns table as return
(
with C as
(
select cast(substring(S.Value, S1.Pos, S2.L) as int) as Number,
stuff(s.Value, 1, S1.Pos + S2.L, '') as Value
from (select #String+' ') as S(Value)
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
union all
select cast(substring(S.Value, S1.Pos, S2.L) as int),
stuff(S.Value, 1, S1.Pos + S2.L, '')
from C as S
cross apply (select patindex('%[0-9]%', S.Value)) as S1(Pos)
cross apply (select patindex('%[^0-9]%', stuff(S.Value, 1, S1.Pos, ''))) as S2(L)
where patindex('%[0-9]%', S.Value) > 0
)
select Number
from C
)
Then, you can do something like this to get the results you were asking for. Note that I broke the query up into 3 parts for clarity. And, obviously, you don't need to declare the table variable and insert data into it.
DECLARE #tbl
TABLE (
COLUMN01 int,
COLUMN02 varchar(max)
)
INSERT INTO #tbl VALUES (1, 'abc"11444,12,13"efg"14,15"hij"16,17,18,19"opqr')
INSERT INTO #tbl VALUES (2, 'ahsdhg"21,22,23"ghshds"24,25"fgh"26,27,28,28"shgshsg')
INSERT INTO #tbl VALUES (3, 'xvd"3142,32,33"hty"34,35"okli"36,37,38,39"adfd')
SELECT COLUMN01, SUBSTRING(COLUMN02, 2, LEN(COLUMN02) - 1) as COLUMN02 FROM
(
SELECT COLUMN01, REPLACE(COLUMN02, ' ', '') as COLUMN02 FROM
(
SELECT COLUMN01, (select ',' + number as 'data()' from dbo.GetNumbersFromText(Column02) for xml path('')) as COLUMN02 FROM #tbl
) t
) tt
GO
output:
COLUMN01 COLUMN02
1 11444,12,13,14,15,16,17,18,19
2 21,22,23,24,25,26,27,28,28
3 3142,32,33,34,35,36,37,38,39
I know you want to do it using SQL. But ones I had nearly the same problem and getting this data to a string using a php or another language, than parsing is a way to do it. For example, you can use this kind of code after receiving the data into a string.
function clean($string) {
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
$string = preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
return preg_replace('/-+/', '-', $string); // Replaces multiple hyphens with single one.
}
For more information you might want to look at this post that I retrieved the function: Remove all special characters from a string
As I said this is an easy way to do it, I hope this could help.

Formatting a number as a monetary value including separators

I need some help with a sql transformation. This part of query that I have been provided with:
'$' + replace(cast((CAST(p.Price1 AS decimal(10,2)) * cast(isnull(p.Multiplier,1) as decimal(10,2))) as varchar), '.0000', '')
Basically, it ends up being a varchar that looks like this: $26980
I need to insert a comma at the thousand and million mark (if applicable). So in this instance, $26,980
What's the easiest way to do that without having to rewrite the whole thing?
Do it on the client side. Having said that, this example should show you the way.
with p(price1, multiplier) as (select 1234.5, 10)
select '$' + replace(cast((CAST(p.Price1 AS decimal(10,2)) * cast(isnull(p.Multiplier,1) as decimal(10,2))) as varchar), '.0000', ''),
'$' + parsename(convert(varchar,cast(p.price1*isnull(p.Multiplier,1) as money),1),2)
from p
The key is in the last expression
'$' + parsename(convert(varchar,cast(p.price1*isnull(p.Multiplier,1) as money),1),2)
Note: if p.price1 is of a higher precision than decimal(10,2), then you may have to cast it in the expression as well to produce a faithful translation since the original CAST(p.Priced1 as decimal(10,2)) will be performing rounding.
If you really must do it in TSQL you can use CONVERT(), but this sort of thing really doesn't belong in the database:
declare #m money = 12345678
-- with decimal places
select '$' + convert(varchar, #m, 1)
-- without decimal places
select '$' + replace(convert(varchar, #m, 1), '.00', '')
You could turn this into a function, it only goes 50 characters back.
DECLARE #input VARCHAR(50)
SELECT #input = '123123123.00'
SELECT #input = CASE WHEN CHARINDEX('.', #input) > offset +1
THEN STUFF(#input, CHARINDEX('.', #input) - offset, 0, ',')
ELSE #input END
FROM (SELECT 3 offset UNION SELECT 7 UNION SELECT 12 UNION SELECT 18 UNION SELECT 25 UNION SELECT 33 UNION SELECT 42) b
PRINT #input
The offset grows by +1 for each position, because it's assuming you've already inserted the commas for the previous positions.