SQL Character extraction - sql

I would like to extract everything on the right side of the "underscore". I want to get 0000. I tried
select right('M_0000',charindex('_','M_0000')-1)
but end up with just 0. Why?

Since you are using CHARINDEX, i assume you are using SQL-SERVER.
So in your second field you should say how many characters you want. You can achieve that by doing LEN('M_0000') - charindex('_') :
select right('M_0000',len('M_0000') - charindex('_','M_0000'))
sqlfiddle demo
You were ending up with just one 0 because charindex('_') is 1, and you are telling the RIGHT function that you want 1 char from the right.
From the docs:
RIGHT ( character_expression , integer_expression )
character_expression Is an expression of character or binary data.
character_expression can be a constant, variable, or column.
character_expression can be of any data type, except text or ntext,
that can be implicitly converted to varchar or nvarchar. Otherwise,
use the CAST function to explicitly convert character_expression.
integer_expression Is a positive integer that specifies how many
characters of character_expression will be returned. If
integer_expression is negative, an error is returned. If
integer_expression is type bigint and contains a large value,
character_expression must be of a large data type such as
varchar(max).

You can use SUBSTRING instead of RIGHT:
select SUBSTRING('M_0000',charindex('_','M_0000')+1, LEN('M_0000')) // start at character n + 1

Related

Remove all trailing decimal points from a number stored as a string

I have a couple of strings (nvarchar data type), one is a whole number and one has decimal points trailing. My goal is to remove decimals and have all values as a whole number.
I tried the code below but it gives me an error for the value with no decimals. Is there a way to accomplish this without a case expression. I'll be using this new column in a join.
SELECT [SOW]
--,LEFT([SOW], CHARINDEX('.', [SOW])-1) as 'TestColumn'
FROM [dbo].[t_Schedule_kdm]
WHERE sow in ('15229.11','11092')
Output:
11092
15229.11
My desired Output:
11092
15229
Just append a dot character so that you'll always find an index:
LEFT(SOW, CHARINDEX('.', SOW + '.') - 1)
It's not clear whether you need to cast the result of that expression to an integer value.
Convert first to the most precision number you could ever have e.g. decimal(9,2) then convert to an int. You can't convert directly from a decimal string to an int.
SELECT [Value]
, CONVERT(int,CONVERT(decimal(9,2),[Value]))
FROM (
VALUES ('15229.11'),('11092')
) x ([Value]);

Different values for these two rounding expressions?

SELECT
ROUND(152.7300, 2, 1), --returns 152.7300
ROUND('152.7300', 2, 1) --returns 152.72
Why does the second rounding expression result in downward rounding to .72 ?
I imagine it has something to do with the VARCHAR input being converted to a numeric, but I can't imagine how that would cause it to lose a decimal value like that.
When you pass a string literal to ROUND, SQL Server converts it to float*. In contrast, 152.7300 is treated as numeric:
In Transact-SQL statements, a constant with a decimal point is automatically converted into a numeric data value, using the minimum precision and scale necessary.
Exact float representation of 152.73 is 152.72999572753906, hence truncation** to the second decimal digit yields 152.72.
* You can check this by passing a non-numeric string, e.g. ROUND('foo', 2, 1). This will produce "Error converting data type varchar to float."
** Passing a value other than zero for the third parameter of ROUND indicates truncation of the number, instead of rounding.
https://learn.microsoft.com/en-us/sql/t-sql/functions/round-transact-sql
ROUND ( numeric_expression , length [ ,function ] )
function
Is the type of operation to perform. function must be tinyint, smallint, or int. When function is omitted or has a value of 0 (default), numeric_expression is rounded. When a value other than 0 is specified, numeric_expression is truncated.

Using SUBSTRING with a column name

I've been trying this all morning and can't find what I'm doing wrong. I have a string, 'XXYY0000' and I need the XX and YY seperatly.
So this works and gets the XX values:
SELECT LEFT(l.LOAN_MATURITY, 2)
FROM LOAN As l
But why is this not working when I need to get the YY values?
SELECT SUBSTRING(l.LOAN_MATURITY, 3, 2)
FROM LOAN As l
I researched and it should give the same output as the MID() function, but it gives me this error.
Msg 8116, Level 16, State 1, Line 1
Argument data type numeric is invalid for argument 1 of substring function.
Why is the data type important for the SUBSTRING function but not the LEFT function?
LEFT:
LEFT ( character_expression , integer_expression )
character_expression
Is an expression of character or binary data. character_expression can be a constant, variable, or column. character_expression can be of
any data type, except text or ntext, that can be implicitly converted
to varchar or nvarchar. Otherwise, use the CAST function to explicitly
convert character_expression.
SUBSTRING:
SUBSTRING ( expression ,start , length )
expression
Is a character, binary, text, ntext, or image expression.
With LEFT there is implicit CAST, with SUBSTRING not. You need to CAST it manually:
SELECT SUBSTRING(CAST(l.LOAN_MATURITY AS VARCHAR(100)), 3, 2)
FROM LOAN As l

Converting data types in SQL Server

I need to change some data types. I have tried using the CAST keyword, but it is not fixing the issue. Any suggestions on how to re-write these two lines with CAST statements?
Data loss might occur when casting from VarChar(100) to VarChar(20).
Code:
SELECT TOP 1 #variableId = variableId
FROM #tempTable
Data loss might occur when casting from NVarChar(512) to NVarChar.
Code:
SELECT myVariable
FROM tableName
I tried doing something like the following, but still produces an error:
CAST((myVariable) as nvarchar)
CAST is used for converting between data types. It sounds more like you should use LEFT instead:
SELECT TOP 1 #variableId = LEFT(variableId,20)
FROM #tempTable
This won't give you any warning as the system assumes you already know you're going to lose the right 80 characters.
For using CONVERT instead of CAST:
CONVERT(nvarchar, myVariable)
Is a valid syntax and also:
CONVERT(varchar(20), myVariable)
But for getting a part of a string we use SUBSTRING() or LEFT() or RIGHT() functions like this:
SUBSTRING( value_expression , start_expression , length_expression )
Returns part of a character, binary, text, or image expression.
LEFT ( character_expression , integer_expression )
Returns the left part of a character string with the specified number of characters.
RIGHT ( character_expression , integer_expression )
Returns the right part of a character string with the specified number of characters.

sql convert error on view tables

SELECT logicalTime, traceValue, unitType, entName
FROM vwSimProjAgentTrace
WHERE valueType = 10
AND agentName ='AtisMesafesi'
AND ( entName = 'Hawk-1')
AND simName IN ('TipSenaryo1_0')
AND logicalTime IN (
SELECT logicalTime
FROM vwSimProjAgentTrace
WHERE valueType = 10 AND agentName ='AtisIrtifasi'
AND ( entName = 'Hawk-1')
AND simName IN ('TipSenaryo1_0')
AND CONVERT(FLOAT , traceValue) > 123
) ORDER BY simName, logicalTime
This is my sql command and table is a view table...
each time i put "convert(float...) part " i get
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to float.
this error...
One (or more) of the rows has data in the traceValue field that cannot be converted to a float.
Make sure you've used the right combination of dots and commas to signal floating point values, as well as making sure you don't have pure invalid data (text for instance) in that field.
You can try this SQL to find the invalid rows, but there might be cases it won't handle:
SELECT * FROM vwSimProjAgentTrace WHERE NOT ISNUMERIC(traceValue)
You can find the documentation of ISNUMERIC here.
If you look in BoL (books online) at the convert command, you see that a nvarchar conversion to float is an implicit conversion. This means that only "float"-able values can be converted into a float. So, every numeric value (that is within the float range) can be converted. A non-numeric value can not be converted, which is quite logical.
Probably you have some non numeric values in your column. You might see them when you run your query without the convert. Look for something like comma vs dot. In a test scenario a comma instead of a dot gave me some problems.
For an example of isnumeric, look at this sqlfiddle