SQL Server - Delete Values after Decimal (non-int field) - sql

Have a ncarchar(MAX) field in SQL table. It has numbers such as 717.08064182582, 39.0676048113, etc. in which I need to only have 3 places after decimal. For instance 717.080, 39.067.
Without converting the field type, would like to get rid of those last n characters, however every row has different number of characters. I believe I could use ROUND (correct me if wrong), but would rather not.

Try this
SELECT CAST(ColumnName AS DECIMAL(18,3))
Without converting it data type As per #vkp Comment
SELECT SUBSTRING(ColumnName ,0,CHARINDEX('.', ColumnName )+4)

select CASE WHEN CHARINDEX('.', Your_column) > 0
THEN SUBSTRING(Your_column, 1, CHARINDEX('.', Your_column) + 3)
ELSE Your_column
END
this is similar as previous answers but more faster and safer

Try this:
SELECT SUBSTRING(Your_column, 1, PATINDEX('%.%', Your_column) + 3)
FROM Your_Table

Related

TSQL extract part of string with regex

i would make a script that iterate over the records of a table with a cursor
and extract from a column value formatted like that "yyy://xx/bb/147011"
only the final number 147011and to put this value in a variable.
It's possible to do something like that?
Many thanks.
You don't need a cursor for this. You can just use a query. The following gets everything after the last /:
select right(str, charindex('/', reverse(str)) - 1 )
from (values ('yyy://xx/bb/147011')) v(str)
It does not specifically check if it is a number, but that can be added as well.
You can also use the below query.
SELECT RIGHT(RTRIM('yyy://xx/bb/147011'),
CHARINDEX('/', REVERSE('/' + RTRIM('yyy://xx/bb/147011'))) - 1) AS LastWord
If numeric value has exact position defined with sample data, then you can do :
SELECT t.*, SUBSTRING(t.col, PATINDEX('%[0-9]%', t.col), LEN(t.col))
FROM table t;

Does the SQL CASE statement treat variables differently from columns?

I have the following code in a stored procedure and am trying to conditionally format a calculated number based on its length (if the number is less than 4 digits, pad with leading zeros). However, my case statement is not working. The "formattedNumber2" result is the one I'm looking for.
I'm assuming the case statement treats the variable strangely, but I also don't know of a way around this.
DECLARE #Number int = 5
SELECT
CASE
WHEN (LEN(CONVERT(VARCHAR, #Number)) > 4)
THEN #Number
ELSE RIGHT('0000' + CAST(#Number AS VARCHAR(4)), 4)
END AS formattedNumber,
LEN(CONVERT(VARCHAR, #Number)) AS numberLength,
RIGHT('0000' + CAST(#Number AS VARCHAR(4)), 4) AS formattedNumber2
I get the following results when I run the query:
formattedNumber numberLength formattedNumber2
-------------------------------------------------
5 1 0005
SQL DEMO
The problem is you are using different data type on your case , integer and string. So the CASE stay with the first type he find and convert the rest.
CASE WHEN (LEN(convert(VARCHAR, #Number)) > 4) THEN convert(VARCHAR, #Number)
This can be done a lot easier with format() since version 2012.
format(n,
'0000')
And that would also handle negative values, which your current approach apparently doesn't.
Prior 2012 it can be handled with basically replicate() and + (string concatenation).
isnull(replicate('-',
-sign(n)), '')
+
isnull(replicate('0',
4
-
len(cast(abs(n) AS varchar(10)))
),
'')
+
cast(abs(n) AS varchar(10))
(It targets integer values, choose a larger length for the varchar casts for bigint.)
db<>fiddle

Sort varchar datatype with numeric characters

SQL SERVER 2005
SQL Sorting :
Datatype varchar
Should sort by
1.aaaa
5.xx
11.bbbbbb
12
15.
how can i get this sorting order
Wrong
1.aaaa
11.bbbbbb
12
15.
5.xx
On Oracle, this would work.
SELECT
*
FROM
table
ORDER BY
to_number(regexp_substr(COLUMN,'^[0-9]+')),
regexp_substr(column,'\..*');
You could do this by calculating a column based on what's on the left hand side of the period('.').
However this method will be very difficult to make robust enough to use in a production system, unless you can make a lot of assertions about the content of the strings.
Also handling strings without periods could cause some grief
with r as (
select '1.aaaa' as string
union select '5.xx'
union select '11.bbbbbb'
union select '12'
union select '15.' )
select *
from r
order by
CONVERT(int, left(r.string, case when ( CHARINDEX('.', r.string)-1 < 1)
then LEN(r.string)
else CHARINDEX('.', r.string)-1 end )),
r.string
If all the entries have this form, you could split them into two parts and sort be these, for example like this:
ORDER BY
CONVERT(INT, SUBSTRING(fieldname, 1, CHARINDEX('.', fieldname))),
SUBSTRING(fieldname, CHARINDEX('.', fieldname) + 1, LEN(fieldname))
This should do a numeric sort on the part before the . and an alphanumeric sort for the part after the ., but may need some tuning, as I haven't actually tried it.
Another way (and faster) might be to create computed columns that contain the part before the . and after the . and sort by them.
A third way (if you can't create computed columns) could be to create a view over the table that has two additional columns with the respective parts of the field and then do the select on that view.

Sum of data in varchar column

i have to sum element in a column(SCENARIO1) that is varchar and contain data like (1,920, 270.00, 0, NULL) but when i try to convert data into int or decimal i get this error :
"he command is wrong when converting value "4582014,00" to int type"
here is my request :
select sum( convert( int, SCENARIO1) )
from Mnt_Scenario_Exercice where code_pere='00000000'
any help please
try this
select sum(cast(replace(SCENARIO1, ',', '.') as decimal(29, 10)))
from Mnt_Scenario_Exercice
where code_pere = '00000000';
If you couldn't convert your '4582014,00' into decimal, there's a chance you have different decimal separator on your server. You could look what it is or just try '.'
4582014,00 should be a decimal
try this (I assume that youre query is working) and changed convert(int into decimal)
select sum(convert(decimal(20,2),replace(SCENARIO1, ',', '.'))) from Mnt_Scenario_Exercice where code_pere='00000000'
The problem is due to the fact that the sum function isn't decoding SCENARIO1 as containing a CSV list of numbers. The way the sum function is usually used is to sum a lot of numbers drawn from multiple rows, where each row provides one number.
Try doing it in two steps. In step 1 convert the table into first normal form perhaps by UNPIVOTING. The 1NF table will have one number per row, and will contain more rows than the initial table.
The second step is to compute the sum. If you want more than one sum in the result, use GROUP BY to create groups, and then select a sum(somecolumn). This will yield one sum for each group.
Try this, I haven't got a way to test yet, but I will test and replace if incorrect.
SELECT sum(CAST (replace(SCENARIO1, ',', '') AS INT))
FROM Mnt_Scenario_Exercice
WHERE code_pere = '00000000';
EDIT: You can use a numeric for the cast if you need 4582014,00 to be 4582014.00
SELECT sum(CAST (replace(SCENARIO1, ',', '.') AS NUMERIC(10,2)))
FROM Mnt_Scenario_Exercice
WHERE code_pere = '00000000';

Removing Characters From SQL String (Search)

Should be a pretty simple one today. I have a column with a list of contracts:
As you see, some contracts have a "-...." at the end. I need to removed this and any character after this (see desired output). Unfortunately, it's not just 1 character (could be multiple/differenct #s). So I imagine it's going to be a right/len/search combo.
Thoughts?
If the contracts all have the same form, the following is almost standard SQL for doing what you want:
select (case when CTNumber like '%-%-%'
then left(CTNumber, 7)
else CTNumber
end) as DesiredOutput
from t
The like syntax is standard, the case is standard, and most databases have a left() function. This does assume that the form of the CTNumber is such that you always want the first seven characters.
You can use patindex to confirm the presence of two dashes. With a double charindex, you can then return the part of the string before the second dash:
select case
when patindex('%-%-%', col1) > 0 then
left(col1, charindex('-', col1, charindex('-', col1) + 1) - 1)
else col1
end as col1
from dbo.YourTable