Error while converting varchar to Decimal - sql

In my table I have a column(Varchar). It contains values like 'abc^1234567^xyz'.
I need to select part of the value and convert it to select the number and convert it to a decimal number and compare this number to a number from another table by joining two tables.
So far I get error while want to convert it from varchar to decimal.
Here is my error message:
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
Here is my code:
SELECT
a.Status,
Cast(SUBSTRING(sourceNatKey, LEN(sourceNatKey)-11,7) As Decimal(18,4)),
b.caseId
FROM AGREEMENT_STATUS a
INNER JOIN APPLICATION_FACT b
ON
Cast(SUBSTRING(sourceNatKey, LEN(sourceNatKey)-11,7) As decimal(18,4)) =
b.caseId

You could use the LIKE operator in the JOIN for such situations.
But if you really have to get a substring from such string ('abc^1234567^xyz'), you could use such construction:
SELECT
a.Status,
Cast(SUBSTRING(sourceNatKey, CHARINDEX('^',sourceNatKey) + 1,CHARINDEX('^',sourceNatKey, CHARINDEX('^',sourceNatKey)+1) - CHARINDEX('^',sourceNatKey) - 1) As decimal(18,4)),
b.caseId
FROM AGREEMENT_STATUS a
INNER JOIN APPLICATION_FACT b
ON
Cast(SUBSTRING(sourceNatKey, CHARINDEX('^',sourceNatKey) + 1,CHARINDEX('^',sourceNatKey, CHARINDEX('^',sourceNatKey)+1) - CHARINDEX('^',sourceNatKey) - 1) As decimal(18,4)) =
b.caseID

You could do this the other way:
SELECT
a.Status,
b.caseId
FROM AGREEMENT_STATUS a JOIN
APPLICATION_FACT af
ON sourceNatKey LIKE '%^' + CAST(b.caseID as varchar(255)) + '^%'
The caseId column has the information in your second column, so that doesn't need to be repeated.

The code SUBSTRING(sourceNatKey, LEN(sourceNatKey)-11,7) will result in ^123456 given the value abc^1234567^xyz. This fails because ^ is non-numeric. Change the offset value from the LEN call to be -10 in order to only retrieve the numeric part of your string.
For further information regarding SUBSTRING, see SUBSTRING (Transact-SQL) Documentation.

Related

SQL Server - Dynamically Filling the column Values with 0's as per the fixed length

I have a column with the given values
MRN
1946
456
27
557
The column values length is fixed.
If at all any value is less than 6characters,then it should concate 0's to the left and make it 6characters length.
The desired output is
MRN
001946
000456
000027
000557
This is called left paddings. In SQL Server, this is typically done with more basic string operations:
select right(replicate('0', 6) + mrn, 6)
If mrn is a number, then use the concat() function:
select right(concat(replicate('0', 6), mrn), 6)
You can also use the FORMAT function for this. (Demo)
SELECT FORMAT(MRN ,'D6')
FROM YourTable
Change the number 6 to whatever your total length needs to be:
SELECT REPLICATE('0',6-LEN(EmployeeId)) + EmployeeId
If the column is an INT, you can use RTRIM to implicitly convert it to a VARCHAR
SELECT REPLICATE('0',6-LEN(RTRIM(EmployeeId))) + RTRIM(EmployeeId)
And the code to remove these 0s and get back the 'real' number:
SELECT RIGHT(EmployeeId,(LEN(EmployeeId) - PATINDEX('%[^0]%',EmployeeId)) + 1)
We can achieve this by adding leading zero's
select RIGHT('0000'+CAST(MRN AS VARCHAR(10)),6)

how to convert the output of sub query into numeric

select rptName
from RptTable
where rpt_id in (
select LEFT(Reports, NULLIF(LEN(Reports)-1,-1))
from repoAccess1
where uid = 'VIKRAM'
)
this is my sql query In which i have use the sub query to access selected field
in this sub query returns
select LEFT(Reports, NULLIF(LEN(Reports)-1,-1))
from repoAccess1
where uid = 'VIKRAM'
Returns
1,2
that means the query should be like
select rptName
from RptTable where rpt_id in (1,2)
But i m getting this error
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to numeric.
could anyone tell me ow to modify to get exact ans
It's a little hard to tell without the concrete table definitions, but I'm pretty sure you're trying to compare different data types to each other. If this is the case you can make use of the CAST or the CONVERT function, for example:
SELECT
[rptName]
FROM [RptTable]
WHERE [rpt_id] IN
(
SELECT
CONVERT(int, LEFT([Reports], NULLIF(LEN([Reports]) - 1, -1)))
FROM [repoAccess1]
WHERE [uid] = 'VIKRAM'
)
UPDATE: Since you have updated your question: The LEFT function returns results of either varchar or nvarchar data type. So the resulting query would be
SELECT
[rptName]
FROM [RptTable]
WHERE [rpt_id] IN('1', '2')
Please note the apostrophes (is this the correct term?) around the values. Since [rpt_id] seems to be of data type int the values cannot implicitly be converted. And that's where the aforementioned CAST or CONVERT come into play.
If I understand correctly, the subquery is returning a single row with a value of '1,2'. This is not a number, hence the error.
Before continuing, let me emphasize that storing values in comma delimited string is not the SQL-way of doing things. You should have one row per id, with proper types and foreign keys defined.
That said, sometimes we are stuck with other people's really bad design decisions. If this is the case, you can use LIKE:
select rptName
from RptTable r
where exists (select 1
from repoAccess1 a
where a.uid = 'VIKRAM' and
',' + a.reports + ',' like '%,' + cast(r.rpt_id as varchar(255)) + ',%'
);
select rptName
from RptTable
where rpt_id in (
select CAST(LEFT(Reports, NULLIF(LEN(Reports)-1,-1)) AS INT) as Val
from repoAccess1
where uid = 'VIKRAM'
)
Your query would work fine when (LEFT(Reports, NULLIF(LEN(Reports)-1,-1)) ) returns either 1 or 2 since SQL Server implicitly converts the varchar value to numeric.
It seems there might be a data issue. One of the data returned by LEFT function is non-numeric. In order to find that particular record you can use isnumeric function. Try like this,
SELECT rptName
FROM RptTable
WHERE rpt_id IN (
SELECT LEFT(Reports, NULLIF(LEN(Reports) - 1, - 1))
FROM repoAccess1
WHERE uid = 'VIKRAM'
AND ISNUMERIC(LEFT(Reports, NULLIF(LEN(Reports) - 1, - 1))) = 1
)

Format sql column when using select

I have the following query to select record but i wan to format the column on the result set.
SELECT
COALESCE(dbo.tblMitchellLandscapeID.PatchSize,0) as PatchSize,
dbo.tblMitchellLandscape.MitchellLandscapeName
FROM tblMitchellLandscapeID
INNER JOIN dbo.tblMitchellLandscape
ON dbo.tblMitchellLandscapeID.MitchellLandscapeID=dbo.tblMitchellLandscape.MitchellLandscapeID
WHERE AssessmentVersionID = #AssessmentVersionID
"PatchSize" is a decimal value so it stored always like two decimals "15.10". All i trying to format to one decimal when the select statement is executed i wan to populate the result set like "15.1" rather than 15.10.
You can just cast it to the format you want:
SELECT CAST(COALESCE(li.PatchSize, 0) as decimal(5, 1)) as PatchSize,
l.MitchellLandscapeName
FROM tblMitchellLandscapeID li INNER JOIN
dbo.tblMitchellLandscape l
ON li.MitchellLandscapeID = l.MitchellLandscapeID
WHERE AssessmentVersionID = #AssessmentVersionID;
Notice the query is also easier to read (and write) if you use table aliases.

I need to remove leading zeros after a decimal point

this is my first time posting here and I am a basic SQL user and need help.
I have a varchar column that stores data like below:
Year.Docid
2007.000000001
2007.000000002
2007.000000003
2007.000000004
2007.000000005
2007.000000006
I need to join this data to another table that does not have all the zeros after the decimal, can someone please show me how to get the data to look like below:
Year Docid
2007.1
2007.2
2007.3
2007.4
2007.5
2007.6
I am using MICROSOFT SQL SERVER 2012
If the format is fixed, i.e. YYYY.NNNNNNNNN, you could just get the last 9 characters, convert them to int, convert the result back to varchar and concatenate back to the first 5 characters:
LEFT([Year.Docid], 5) + CAST(CAST(RIGHT([Year.Docid], 9) AS int) AS varchar(10))
However, it would make more sense to store Year and Docid as two separate int columns, in both tables. It is much easier to assemble them just for the output than do this processing every time and join on the results of it.
In SQL Server, assuming both columns are varchar, something like this should do you:
select *
from table_1 t1
join table_2 t2 on t2.docid = left(t2.docid,4)
+ '.'
+ convert(varchar,convert(int,right( t2.docid, len(t2.docid)-5 )))
You should bear in mind that making the one table's column an expression means that for that table/column, the query optimizer cannot use any indexes in the query plan.
This is a bit of work, but accomplishes the task of removing the zeros from the right of the dot:
SELECT SUBSTRING(YearDocid, 0, CHARINDEX('.', yearDocId)) +
REPLACE(SUBSTRING(yearDocId,
CHARINDEX('.', yearDocId),
LEN(yearDocID)),
'0', '')
FROM tab1;
sqlfiddle demo
To turn the long format into the short format:
SELECT LEFT('2007.000000001',5) + CAST(CAST(RIGHT('2007.000000001',LEN('2007.000000001')-5) AS int)AS VARCHAR)
...
To use that in a join:
SELECT
...
FROM
TABLE_1 T1
INNER JOIN TABLE_2 T2
ON LEFT(T1.pk,5) + CAST(CAST(RIGHT(T1.pk,LEN(T1.pk)-5) AS int)AS VARCHAR) = T2.pk
SELECT CONCAT(PARSENAME([Col_Varchar],2),'.',CONVERT(INT,PARSENAME([Col_Varchar],1))) FROM Tbl_sample

Msg 8114, Level 16, State 5, Line 1 Error converting data type varchar to numeric

Select
CAST(de.ornum AS numeric) + 1 as ornum2
from Cpaym as de
left outer join Cpaym as de1 on CAST(de.ornum AS numeric) = de1.ornum
where ISNUMERIC(de.ornum) = 1
I'm trying to get the missing sequence number, but I am getting an error:
Msg 8114, Level 16, State 5, Line 1 Error converting data type varchar to numeric.
You have a CAST() in your join predicate, which is evaluated BEFORE the WHERE clause. If de.ornum is not numeric, then this cast will fail.
Also, IsNumeric() doesn't catch all numeric types, but it's perhaps good enough in most cases. Here's the documentation: http://technet.microsoft.com/en-us/library/ms186272(v=sql.105).aspx and here is one (of many) articles describing the problems with IsNumeric(): http://classicasp.aspfaq.com/general/what-is-wrong-with-isnumeric.html.
There are a few things you can do:
Fix your schema so that a column named ornum actually contains a number in all tables that have it.
Use a CASE expression in your join predicate (slow, but it'll work): ... ON CASE WHEN ISNUMERIC(de.ornum) = 1 THEN CAST(de.ornum AS numeric) ELSE NULL END = de1.ornum
Use a derived table to pre-convert before the join (also slow, but perhaps less slow -- check the execution plan)
Code:
FROM (
SELECT de.ornum
FROM Cpaym AS de
WHERE IsNumeric(de.ornum) = 1
) AS de
LEFT OUTER JOIN ...