How to less numeric value from data type varchar.
For example, I have table which contains value like '2019-02-15', '2019-02-20 10:00:15.000', '3476', '3478956', and I need to less -1 from all of them. How can i do that.
Below is sample query
CREATE TABLE dbo.TestTable (SampleData VARCHAR(100))
INSERT INTO dbo.TestTable ([SampleData])
VALUES ('2019-02-15')
,('2019-02-20 10:00:15.000')
,('3476')
,('3478956')
SELECT * FROM dbo.TestTable
If 2012+, you can use try_convert() within a case statement
Example
SELECT *
,RequiredData = case when try_convert(int ,SampleData) is not null then convert(varchar(100),try_convert(int,SampleData)-1)
when try_convert(date,SampleData) is not null then convert(varchar(100),dateadd(DAY,-1,try_convert(date,SampleData)) )
end
FROM dbo.TestTable
Returns
SampleData RequiredData
2019-02-15 2019-02-14
2019-02-20 10:00:15.000 2019-02-19
3476 3475
3478956 3478955
Related
I'm quite new to T-SQL and currently struggling with an insert statement in my stored procedure: I use as a parameter in the stored procedure a list of ids of type INT.
If the list is NOT empty, I want to store the ids into the table Delivery.
To pass the list of ids, i use a table type:
CREATE TYPE tIdList AS TABLE
(
ID INT NULL
);
GO
Maybe you know a better way to pass a list of ids into a stored procedure?
However, my procedure looks as follows:
-- parameter
#DeliveryModelIds tIdList READONLY
...
DECLARE #StoreId INT = 1;
-- Delivery
IF EXISTS (SELECT * FROM #DeliveryModelIds)
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT ID FROM #DeliveryModelIds;
If the list has values, I want to store the values into the DB as well as the StoreId which is always 1.
If I insert the DeliveryIds 3,7,5 The result in table Delivery should look like this:
DeliveryId | StoreId | DeliveryModelId
1...............| 1...........| 3
2...............| 1...........| 7
3...............| 1...........| 5
Do you have an idea on how to solve this issue?
THANKS !
You can add #StoreId to your select for your insert.
...
IF EXISTS (SELECT * FROM #DeliveryModelIds)
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT ID, #StoreId FROM #DeliveryModelIds;
Additionally, if you only want to insert DeliveryModelId that do not currently exist in the target table, you can use not exists() in the where clause like so:
...
IF EXISTS (SELECT * FROM #DeliveryModelIds)
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT dmi.ID, #StoreId
FROM #DeliveryModelIds dmi
where not exists (
select 1
from MyDb.Delivery i
where i.StoreId = #StoreId
and i.DeliveryModeId = dmi.ID
);
You need to modify the INSERT statement to:
INSERT [MyDB].[Delivery] ([DeliveryModelId], [StoreId])
OUTPUT inserted.DeliveryId
SELECT ID, 1 FROM #DeliveryModelIds;
So you are also selecting a literal, 1, along with ID field.
I have a column which has varchars like "172.54". I am trying to insert into another table where this columns datatype is float. I am getting error saying can not convert datatype varchar to float. So I do
SELECT *
FROM TBL
WHERE ISNUMERIC(COLNAME) <> 1
And I get no results. But casting is not working. So I look and I have empty strings in that column. So I try to
SELECT *
FROM TBL
WHERE COLNAME = ''
And also every other different amount of spaces.
I ultimately just want to convert the empty strings to null
Also len(colname) = 1
declare #test varchar(10) = ' ' -- any number of spaces is equivalent to ''
select try_convert( float, #test ) as floatval -- '' gives you 0
select case when #test = '' then NULL else try_convert( float, #test ) end as floatval -- value '' returns NULL instead of 0
I guess you column has some characters other than numeric data. Also empty string will be converted to zero it will not throw error.
To filter Numeric data use
COLNAME not like '%[^0-9]%'
Try something like this
insert into tablename (col1,col2)
SELECT col1,col2 FROM TBL
COLNAME not like '%[^0-9]%'
I am trying to create view by filtering some table, and include some converted to different type column into select list. View filter excludes from result set rows in which this column can not be converted to that type. Then I select rows from this view and filter rows using this converted column. And I always get error Conversion failed when converting the nvarchar value '2aaa' to data type int
SQL Fiddle
MS SQL Server 2008 Schema Setup:
create table _tmp_aaa (id int identity(1, 1), value nvarchar(max) not null)
go
insert _tmp_aaa (value) values ('1111'), ('11'), ('2aaa')
go
create view _tmp_v_aaa
as
select id, cast(value as int) as value from _tmp_aaa where value like '1%'
go
Query 1:
select * from _tmp_v_aaa where value = 11
Are there any workarounds?
Add to your view ISNUMERIC to check if string is numeric value:
CREATE VIEW _tmp_v_aaa
AS
SELECT
id,
[value] = CAST((CASE WHEN ISNUMERIC([value]) = 1 THEN [value] ELSE NULL END) AS INT)
FROM _tmp_aaa
WHERE [value] LIKE '1%'
AND ISNUMERIC([value]) = 1
I tried some tricks... Obviously the optimizer tries to hand down your where criterium where it is not yet tranformed. This is one problem to be solved with a. multi-statement function. Their biggest disadvantage is the advantage in this case: the optimizer will not look into it, but just take their result "as is":
create function fn_tmp_v_aaa()
returns #tbl table(id INT, value INT)
as
BEGIN
INSERT INTO #tbl
select id, cast(value as int) as value from _tmp_aaa where value like '1%'
RETURN;
END
select * from dbo.fn_tmp_v_aaa() where value=11;
If you look at the execution plan , predicates are passed down to the table something like....
And your query gets translated to something like .....
select id, cast(value as int) as value
from tmp_aaa
where CONVERT(INT, value,0) like '1%'
AND CONVERT(INT, value,0) = CONVERT(INT, 11,0)
Now if you run this query you will get the same error you get when you query against the view.
Conversion failed when converting the nvarchar value '2aaa' to data type int.
When the predicate CONVERT(INT, value,0) like '1%' is converted , you have INT on one side of the expressions and varchar on another, INT being the higher precedence, sql server tries to convert whole expression to INT and fails hence the error message.
I'm running into a really odd error using a SQL Server Common Table Expression (CTE).
I think it is easiest to explain my issue by giving a code example.
CREATE TABLE #Test1 (TestCol varchar(3));
INSERT INTO #Test1 VALUES ('012')
INSERT INTO #Test1 VALUES ('ABC')
--This simple shows the Cast works as expected, and only on rows where the TestCol value is numeric
SELECT TestCol, CAST(TestCol as int) as IntCast
FROM #Test1
WHERE ISNUMERIC(TestCol) = 1;
--Here I create a cte using the same SQL as show above.
with cte as (
SELECT
TestCol, CAST(TestCol as int) as IntCast
FROM #Test1
WHERE ISNUMERIC(TestCol) = 1
)
/*
I have two examples below. The first can be executed to check for the existence of our 'ABC' value. It doesn't show up, which is expected.
The Second example, simple checks to see if our IntCast column is greater than 10. This throws an exception
*/
--SELECT * FROM cte
SELECT * FROM cte WHERE IntCast > 10
DROP TABLE #Test1
The exception here is
Conversion failed when converting the varchar value 'ABC' to data type int
I'm curious as to where this is occurring?
with cte as (
SELECT TestCol, Case when ISNUMERIC(TestCol) = 1 then CAST(TestCol as int) else NULL end as IntCast FROM #Test1
)
I have the following Query:
create table #Result (Reward varchar(40), Value MONEY);
insert #Result exec GetCurrentCycleQualifierStatusByAccountId #AccountId=76011;
with cteFirstResults as
(select Reward, round(Value,2) as Value from #Result where Reward like '%Balance%'),
cteSecondResults as
(select Reward, convert(INTEGER, Value) as Value from #Result where Reward NOT like '%Balance%')
select * from cteFirstResults
UNION ALL
select * from cteSecondResults;
drop table #Result;
When running a select * individually against each "cte" table, I get the results I want.
But when run all together, I get something like:
Reward Value
------ -----
Daily Balance 4709.00
Value A 1.00
Value B 9.00
I want the Value A/Value B data to show without any decimal values as they do when running a select against the table directly. How do I combine the two queries into one to show this data correctly?
Round(value,0) does nothing.
I can not change the sproc from which I'm gathering the data, but I can make the temp table any way I like.
Thanks,
Jason
The solution:
create table #Result (Reward varchar(40), Value MONEY);
insert #Result exec GetCurrentCycleQualifierStatusByAccountId #AccountId=76011;
With cteFirstResults as
(
Select Reward, Value
From #Result
Where Reward like '%Balance%'
)
, cteSecondResults as
(
Select Reward, cast(Value as int) as Value
From #Result
Where Reward Not like '%Balance%'
)
Select Reward, Cast( Value As varchar(max)) As Value
From cteFirstResults
Union All
Select Reward, Cast( value As varchar(max)) as Value
From cteSecondResults;
drop table #Result;
The problem is the integers are being implicitly cast to decimal because they are being represented in a decimal column.
If you just want the values displayed, cast them both to strings.
CREATE TABLE #test
(
test decimal(9,2)
)
CREATE TABLE #test2
(
test int
)
INSERT INTO #test (test)
SELECT 1.25 UNION ALL
SELECT 172813.99
INSERT INTO #test2 (test)
SELECT 134 UNION ALL
SELECT 41
SELECT CAST(test as varchar(max)) FROM #Test
UNION ALL
SELECT CAST(test as varchar(max)) FROM #Test2
Results:
1.25
172813.99
134
41
In a union SQL Server will assume that the datatype of the second select is the same as the first and where it can convert them, do so. You will have to beat it at its own game and do you own conversion
In the final select (the one with the Union) massage the data in both cases to be a string. Format the output as desired before converting it to a string.
EACH Sql Server column can only have 1 data type.
round(money,4) returns a money(4)*
convert(int) returns an int
Based on data type precedence
#13. money
#16. int
The resultant column is money(4). Therefore ALL values in the column will be formatted using money(4).
Your options are
convert(float) across both - downside: a value of 1.1 is shown as 1.1, not 1.10
convert(varchar) - you have stated you don't want this, and it changes the data type to the receiving program
FWIW
Round(value,0) does nothing.
It does do something. It burns CPU rounding an int value to another int value (of the same value). Incidentally, the resultant type is (still) "int". This has nothing to do with formatting.
REF:
declare #m money
set #m = 12.3233
select SQL_VARIANT_PROPERTY(round(#m,2), 'basetype') -- money
select SQL_VARIANT_PROPERTY(round(#m,2), 'precision') -- 19
select SQL_VARIANT_PROPERTY(round(#m,2), 'scale') -- 4