How to convert multiple varchar values into smallint - sql

Pardon me, I was trying hard to find the answer, but most of the questions are related in the forum related to converting one value, not the whole set.
I am trying to pass the subquery values to the main query but the subquery returning varchar and the main query column is accepting smallint. I tried cast and convert but didn't help me.
select time_off_type_no
from schedtime
where activity_no in (select AT_NUMBERS from ACTIVITY where AT_ID = 105)
This query is throwing the following exception
Conversion failed when converting the varchar value '483,484,485,486,487,488,489' to data type smallint
Any advice on how to convert the values much appreciated.
Following query returning '483,484,485,486,487,488,489' and I want to convert all the values to SmallInt or int to pass it to the main query.
select AT_NUMBERS
from ACTIVITY
where AT_ID = 105

Please try nested casting like:
SELECT CAST(CAST(AT_NUMBERS AS DECIMAL) AS SMALLINT) from ACTIVITY where AT_ID=105
EDIT: Since the returned value is a comma-delimited string, I think this would help if the version of SQL Server is at least 2016
;with cte (ID) as (
Select string_split (AT_NUMBERS,',') as ID
from ACTIVITY
where AT_ID=105
)
select time_off_type_no from schedtime where activity_no in (
SELECT CAST(CAST(ID AS DECIMAL) AS SMALLINT) from cte
)
If SQL SERVER version is below 2016, we'll need to develop our own split function. You can find examples in How to split a comma-separated value to columns
Try this as an example if so, working in Sql Server 2008:
DECLARE #t TABLE
(
EmployeeID INT,
Certs VARCHAR(8000)
)
INSERT #t VALUES (1,'B.E.,MCA, MCDBA, PGDCA'), (2,'M.Com.,B.Sc.'), (3,'M.Sc.,M.Tech.')
SELECT EmployeeID,
LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS Certs
FROM
(
SELECT EmployeeID,CAST('<XMLRoot><RowData>' + REPLACE(Certs,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x
FROM #t
)t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)
Ref: https://blog.sqlauthority.com/2015/04/21/sql-server-split-comma-separated-list-without-using-a-function/

I think you need to split the string by comma if these (483,484,485,486,487,488,489) are individual numbers. If this is whole integer value, not even Big Int limit is like this.
See MS documentation:
https://learn.microsoft.com/en-us/sql/t-sql/data-types/int-bigint-smallint-and-tinyint-transact-sql?view=sql-server-2017
If your SQL server version is more than 2016 or more, then you can use string_split function in this way.
--Use try_cast or Try_convert to avoid any conversion error as well.
select Try_cast(value as int) Integervalue from string_split ('483,484,485,486,487,488,489',',')
Output:
Integervalue
483
484
485
486
487
488
489
--this will work if it is pure integer value, else it needs to be converted to decimal.
Please make sure to use cross apply if you are using against tables.
If it is less than 2016, you might have to build one string split function as mentioned here.
Splitting the string in sql server

Related

Union leads to error converting varchar to numeric

I'm reposting my question from yesterday with the addition of code.
I'm creating a new table LAB_RESULT as a union of two tables (Labs and CTE). A column called result_num (numeric (18,5)) is causing problems in LAB_RESULT.
Table LAB_RESULT is declared first with explicit data types.
CREATE TABLE dbo.LAB_RESULT
(
[LAB_RESULT_CM_ID] VARCHAR (36),
[RESULT_NUM] NUMERIC (18,5)
)
INSERT INTO [dbo].[LAB_RESULT] (LAB_RESULT_CM_ID, RESULT_NUM)
SELECT LAB_RESULT_CM_ID, RESULT_NUM
FROM [etl].[lab_result]
LAB_RESULT draws from varchar columns in tables LABS and CTE. I have used try_cast in both A and B to make sure nothing slips through.
So when I select from (LABS U CTE), I get:
Msg 8114
Error converting data type varchar to numeric
but when I select from only LABS or only CTE (all there just commented out) the data loads fine.
This is happening even if I use cast(null as numeric).
SELECT LAB_RESULT_CM_ID, RESULT_NUM
FROM
((SELECT
NEWID() AS LAB_RESULT_CM_ID,
CAST(NULL AS NUMERIC(18, 5)) AS RESULT_NUM
FROM [dbo].[Labs] as labs
UNION
(SELECT
NEWID() as LAB_RESULT_CM_ID,
CAST(NULL as NUMERIC(18, 5)) AS RESULT_NUM
FROM CTE)
What gives? I would really appreciate some insight. TIA!

Setting a variable in a SQL WHERE clause to be used in SELECT

I'm using Transact-SQL with Microsoft SQL Server, and we have a query that looks like this:
SELECT Cast( Cast ( Cast(XMLBlob as XML).query(N'//continent/forest/tree/age/Text()') as nvarchar) as bigint),
AnotherField
FROM [MyDB].[dbo].[mytable]
WHERE Cast( Cast ( Cast(XMLBlob as XML).query(N'//continent/forest/tree/age/Text()') as nvarchar) as bigint)
between 10 and 100
The XML cast is an expensive operation, and since it's used in both the WHERE and SELECT, it seems like I should be able to save it away as a variable in the WHERE (which, by order of operations, is evaluated before the SELECT), and use it in the SELECT instead of having to cast again. Is this possible?
You could use an inner query where you retrieve the XML value. Then outside the inner query you both return that bigint value and filter the values you want:
SELECT innerTable.Age, innerTable.AnotherField
FROM (
SELECT Cast( Cast ( Cast(XMLBlob as
XML).query(N'//continent/forest/tree/age/Text()') as nvarchar) as bigint) AS Age,
AnotherField
FROM [MyDB].[dbo].[mytable]
) AS innerTable
WHERE innerTable.Age between 10 and 100
By the way... why do you need a bigint to store Age? If you are storing years looks like overkill, even for those trees that live thousands of years :)

Finding max value for a column containing hierarchical decimals

I have a table where the column values are like '1.2.4.5', '3.11.0.6',
'3.9.3.14','1.4.5.6.7', N/A, etc.. I want to find the max of that particular column. However when i use this query i am not getting the max value.
(SELECT max (CASE WHEN mycolumn = 'N/A'
THEN '-1000'
ELSE mycolumn
END )
FROM mytable
WHERE column like 'abc')
I am getting 3.9.3.14 as max value instead of 3.11....
Can someone help me?
Those aren't really decimals - they're strings containing multiple dots, so it's unhelpful to think of them as being "decimals".
We can accomplish your query with a bit of manipulation. There is a type build into SQL Server that more naturally represents this type of structure - hierarchyid. If we convert your values to this type then we can find the MAX fairly easily:
declare #t table (val varchar(93) not null)
insert into #t(val) values
('1.2.4.5'),
('3.11.0.6'),
('3.9.3.14'),
('1.4.5.6.7')
select MAX(CONVERT(hierarchyid,'/' + REPLACE(val,'.','/') + '/')).ToString()
from #t
Result:
/3/11/0/6/
I leave the exercise of fully converting this string representation back into the original form as an exercise for the reader. Alternatively, I'd suggest that you may want to start storing your data using this datatype anyway.
MAX() on values stored as text performs an alphabetic sort.
Use FIRST_VALUE and HIERARCHYID:
SELECT DISTINCT FIRST_VALUE(t.mycolumn) OVER(
ORDER BY CONVERT(HIERARCHYID, '/' + REPLACE(NULLIF(t.mycolumn,'N/A'), '.', '/') + '/') DESC) AS [Max]
FROM #mytable t

Check if field is numeric, then execute comparison on only those field in one statement?

This may be simple, but I am no SQL whiz so I am getting lost. I understand that sql takes your query and executes it in a certain order, which I believe is why this query does not work:
select * from purchaseorders
where IsNumeric(purchase_order_number) = 1
and cast(purchase_order_number as int) >= 7
MOST of the purchar_order_number fields are numeric, but we introduce alphanumeric ones recently. The data I am trying to get is to see if '7' is greater than the highest numeric purchase_order_number.
The Numeric() function filters out the alphanumeric fields fine, but doing the subsequent cast comparison throws this error:
Conversion failed when converting the nvarchar value '124-4356AB' to data type int.
I am not asking what the error means, that is obvious. I am asking if there is a way to accomplish what I want in a single query, preferably in the where clause due to ORM constraints.
does this work for you?
select * from purchaseorders
where (case when IsNumeric(purchase_order_number) = 1
then cast(purchase_order_number as int)
else 0 end) >= 7
You can do a select with a subselect
select * from (
select * from purchaseorders
where IsNumeric(purchase_order_number) = 1) as correct_orders
where cast(purchase_order_number as int) >= 7
try this:
select * from purchaseorders
where try_cast(purchase_order_number as int) >= 7
have to check which column has numeric values only.
Currently, in a table every field is setted with nvarchar(max) Like tableName (field1 nvarchar(max),field2 nvarchar(max),field3 nvarchar(3)) and tableName has 25lac Rows.
But on manually Check Field2 Contain the numeric Values Only... How to Check With t-sql that in the Complete Column (Field2) has numeric Value or not/null value with Longest Length in the Column!

Conversion failed when converting the varchar value to data type int

i have this query and its work fine for me
SELECT STUFF(
(SELECT ','+SLT_SubListName FROM sublists where SLT_SubListId in (1,2) FOR XML PATH('')),1,1,'');
but when i change the in parameters (1,2) into the 'select SBS_SubListId from subscriber where SBS_SubscriberId=1'
which also return the 1,2
SELECT STUFF(
(SELECT ','+SLT_SubListName FROM sublists where SLT_SubListId in (select SBS_SubListId from subscriber where SBS_SubscriberId=1
) FOR XML PATH('')),1,1,'');
its giving me the error which is the following
Conversion failed when converting the varchar value '1,2,4,5' to data type int.
if anybody needs i can also post my table schema here.
thanks
you have to first split these comma sepered values on comma bases, and then apply converrsion.
I suspect tht your subquery is returning one entry of "1,2,4,5" which is not an integer. You need to get it to return 4 rows with one of these in each.
If you are doing this - show the results of the subquery - then you may have type differences.
Since your subquery seems to be returning the varchar '1,2,4,5', you can try the query using CONTAINS:
SELECT STUFF(
(SELECT ','+SLT_SubListName FROM sublists where CONTAINS((select SBS_SubListId from subscriber where SBS_SubscriberId=1), SLT_SubListId
) FOR XML PATH('')),1,1,'');
That way it treats the results from the subquery as text.