Error in converting value from char to money - sql-server

I have a table tableA that contains a column [Amount] of datatype varchar.
It has values like:
47980.89
333652.61
332388.84
374664.48
368715.26
371689.33
371689.33
368715.26
374664.48
Now when I run my query, it runs successfully but gives different output each time
SELECT
sum(convert(float, Amount))
FROM tableA
and when I try this other statement, I get an error
Cannot convert a char value to money. The char value has incorrect syntax.
Code:
SELECT
sum(convert(money, Amount))
FROM tableA
I want to have sum of the column [Amount]

this should do it:
select Sum(isnull(cast(amount as float),0)) from #t
or you need it to be money data-type
select Sum(isnull(cast(amount as money),0)) from #t
fiddle demo

Try Like this
SELECT SUM(CAST(Amount AS MONEY)) From TableA where ISNUMERIC(Amount)=1

Related

SQL Server 2014: How to convert a VARCHAR column mixed with characters and numbers to corresponding numbers

I have a column called result in SQL Server 2014 which has various kinds of lab test results. The values for result can be characters, numbers (integer or decimals or scientific notations) like this:
positive
negative
not detect
n/a
101
15.3
78.002
-12.1
3.49952E-10
7.3E9
I want to only select those representing numbers, which are...
101
15.3
78.002
-12.1
3.49952E-10
7.3E9
And, I want to convert them into a numeric column with the corresponding values. I also want to get AVG, stdev, min, and max of them.
Can someone help me please?
Thanks a lot!
You could use ISNUMERIC function and CAST it to number
DECLARE #SampleData AS TABLE (Value varchar(30))
INSERT INTO #SampleData
VALUES ('positive'),('negative'),('101'),('15.3'),
('78.002'),('-12.1'),('3.49952E-10'),('7.3E9')
SELECT CAST(sd.[Value] AS float) AS Value
FROM #SampleData sd
WHERE isnumeric(sd.[Value]) = 1
Demo link: Rextester
In SQL Server 2012 and newer, you can also use the TRY_CAST function to try to convert a string to a numeric value - if it fails, it will not crash and burn, but instead just simply return NULL.
Based on that, you could use something like this:
-- define a CTE - an "inline" view which handles the conversion
;WITH CTE AS
(
SELECT NumValue = TRY_CAST(YourColumnName AS FLOAT)
FROM dbo.YourTable
)
-- select only those rows from the CTE that have a non-NULL "NumValue"
SELECT *
FROM CTE
WHERE NumValue IS NOT NULL
You could also use pattern matching by using LIKE operator,
SELECT AVG(NumValue) AS Average
,STDEV(NumValue) AS StDev
,MIN(NumValue) AS Min
,MAX(NumValue) AS Max
FROM
(SELECT CONVERT(FLOAT,YourColumn) AS NumValue
FROM YourTable
WHERE YourColumn LIKE '%[0-9]%') x
This subquery will display any data that has number in it, and would return error if there is alphanumeric data other than exponential notation (i.e 3.49952E-10), in that case you could just specified the pattern after LIKE operator.
by using LIKE operator we can restrict string data
;WITH Cte (TextData)
AS
(
SELECT 'positive' UNION ALL
SELECT 'negative' UNION ALL
SELECT 'not detect' UNION ALL
SELECT 'n/a' UNION ALL
SELECT '101' UNION ALL
SELECT '15.3' UNION ALL
SELECT '78.002' UNION ALL
SELECT '-12.1' UNION ALL
SELECT '3.49952E-10'UNION ALL
SELECT '7.3E9'
)
SELECT *
FROM Cte
WHERE TextData LIKE '%[0-9]%'

Conversion failed when converting the nvarchar value 'test' to data type int

Context: SQL Server 2008
I have a table mytable which contains two NVARCHAR columns id, title.
All data in the id column are in fact numeric, except one row which contains the value 'test'.
I want to get all ids between 10 and 15 so I need SQL Server to convert id column values to INTEGER.
I use ISNUMERIC(id) = 1 to eliminate the non numeric values first but SQL Server is being rather weird with this query.
SELECT
in.*
FROM
(SELECT
id, title
FROM
mytable
WHERE
ISNUMERIC(id) = 1) in
WHERE
in.id BETWEEN 10 AND 15
This query causes the following error:
Conversion failed when converting the nvarchar value 'test' to
data type int.
The inner query eliminates the row with the 'test' id value so 'in' shouldn't contain it. Why is SQL Server still trying to convert it?
Am I missing something? How can I get around this?
P.S. I tried WHERE CAST(in.id AS INTEGER) BETWEEN 10 AND 15 but didn't work either.
Use TRY_CONVERT function, it's very handy.
SELECT id,
title
FROM mytable
where TRY_CONVERT(int, id) is not NULL
and TRY_CONVERT(int, id) BETWEEN 10 and 15
TRY_CONVERT returns null if the conversion fails.
And for you error, I suppose that the Query Optimizer messes something up here. Take a look at the execution plan, maybe it's filtering values between 10 and 15 at the first place. My solution will always work.
As the other commenter said in your case the BETWEEN function is done before ISNUMERIC. Here is a simple example:
select * into #temp2
from (
select 'test' a
union
select cast(1 as varchar) a
union
select cast(2 as varchar) a
union
select cast(3 as varchar) a
)z
SELECT a FROM (
SELECT a FROM #temp2 WHERE ISNUMERIC(a) = 1
) b
WHERE b.a BETWEEN 10 AND 15
This simple query is an alternative:
SELECT a
FROM #temp2
WHERE ISNUMERIC(a) = 1
and a BETWEEN 10 AND 15
I should add one more way with XML style:
SELECT *
FROM mytable
WHERE CAST(id as xml).value('. cast as xs:decimal?','int') BETWEEN 10 AND 15
Convert id to XML, convert the value in xs:decimal and then convert to integer. If there is not numeric value it will be converted into NULL.
Here you can read about XML type casting rules (link).
Could create a new field to do the search on:
Select id, title
from (Select id, title, case id when 'test' then null else cast(id as int) end as trueint from mytable) n
where n.trueint between 10 and 15
OR
Select id, title
from mytable
where case isnumeric(id) when 1 then cast(id as int) else null end between 10 and 15
One possibility is to force the engine to work this in two steps:
DECLARE #tbl TABLE(id NVARCHAR(MAX),title NVARCHAR(MAX));
INSERT INTO #tbl
SELECT id, title FROM mytable WHERE ISNUMERIC(id) = 1;
SELECT t.*
FROM #tbl t
WHERE CAST(t.id AS INT) BETWEEN 10 AND 15

SQL Grouping and Counting based on dates

Getting nowhere here and seems so simple.
Test data is:
declare #table table(SpellAdminsionDate datetime, SpellDischargeDate datetime, Pat_code varchar(10))
insert into #table (SpellAdminsionDate, SpellDischargeDate, Pat_code) values('2016-09-12 15:55:00:000','2016-09-19 20:20:00:000','HEY3052275')
insert into #table(SpellAdminsionDate, SpellDischargeDate, Pat_code) values ('2016-09-07 17:17:00:000','2016-09-17 18:40:00:000','HEY0810155')
insert into #table(SpellAdminsionDate, SpellDischargeDate, Pat_code) values ('2016-09-14 16:50:00:000','2016-09-17 18:01:00:000','HEY1059266')
insert into #table(SpellAdminsionDate, SpellDischargeDate, Pat_code) values ('2016-09-15 02:47:00:000','2016-09-15 17:28:00:000','HEY0742883')
insert into #table(SpellAdminsionDate, SpellDischargeDate, Pat_code) values ('2016-08-27 00:11:00:000','2016-09-14 12:49:00:000','HEY3050628')
insert into #table(SpellAdminsionDate, SpellDischargeDate, Pat_code) values ('2016-09-10 12:24:00:000','2016-09-13 20:00:00:000','HEY0912392')
insert into #table(SpellAdminsionDate, SpellDischargeDate, Pat_code) values ('2016-09-12 12:51:00:000','2016-09-13 19:55:00:000','HEY0908691')
Select * from #table`
Below is my simple code displaying the same thing:
SELECT c.SpellAdmissionDate,
c.SpellDischargeDate,
c.Pat_Code
FROM [CommDB].[dbo].[vwCivicaSLAM1617Live] c
WHERE c.Hrg_Code like 'VA%'
and c.Pat_Code like 'HEY%'
ORDER BY c.SpellDischargeDate desc
All I am after is a COUNT per day of active patients, for example take the 12/09/2016 on that date the result would be 5 (based on the test data) as the other 2 cam in after the 12th.
If it makes it easier I do have a date reference table called DATE_REFERENCE which has every date available to me.
Allowing for the possibility of having no patients on a day then you want to use your date reference table as the primary and left join to the patient information. You don't identify a column name so I just used [datecol].
SELECT
d.[datecol] the_date
, count(DISTINCT c.Pat_Code) num_patients
FROM DATE_REFERENCE d
LEFT JOIN [CommDB].[dbo].[vwCivicaSLAM1617Live] c
ON d.[datecol] BETWEEN c.SpellAdmissionDate AND c.SpellDischargeDate
AND c.Hrg_Code LIKE 'VA%'
AND c.Pat_Code LIKE 'HEY%'
GROUP BY
d.[datecol]
ORDER BY
d.[datecol] DESC
I suspect there may be more than this required, but without sample data and expected results it is difficult to know what you really need.
nb. I assume the date in that date_reference table is at midnight (00:00:00) or has a data type of date (without hours/minutes etc.)
Is this what you want?
SELECT dr.date,
(SELECT COUNT(*)
FROM [CommDB].[dbo].[vwCivicaSLAM1617Live] c
WHERE dr.date between c.SpellAdmissionDate and c.SpellDischargeDate) as cnt_per_day
FROM DATE_REFERENCE dr
Add the filters you want to the correlated query .
You can achieve this by joining to your date reference table and counting by a distinct of the patient reference
SELECT
dateRef
,COUNT(DISTINCT Pat_Code) AS PatCount
FROM #table t
RIGHT JOIN #date_reference
ON SpellAdminsionDate <= dateRef
AND SpellDischargeDate >= dateRef
GROUP BY dateRef;
Active count of patients per date can be achieved by (for temp data provided here)
SELECT DISTINCT CAST(T1.SPELLADMINSIONDATE AS DATE)
AdmissionDate,PATIENTS.TotalActive
FROM #TABLE T1
CROSS APPLY (SELECT COUNT(*)TotalActive FROM #TABLE T2 WHERE
CAST(T2.SPELLADMINSIONDATE AS DATE)<=CAST(T1.SPELLADMINSIONDATE AS DATE)) PATIENTS
I think you need to bring the DATE_REFERENCE table to the Query If it contains all the day dates that you need to count patients based on them, But here is a sample of how may you get the required result form this table only
Select DISTINCT c.SpellAdmissionDate, count(c.Pat_code) as PCounter
From [CommDB].[dbo].[vwCivicaSLAM1617Live] c
GROUP BY c.SpellAdmissionDate
ORDER BY c.SpellAdmissionDate desc

Insert sum of rows and display it in the same table

I have a table as shown below
I want to insert the row below each employee having data as like same employeecode, employeename, project as 'bench', expected end & start dates as null , install capacity as sum of all install capacities of that employees-184 and allocation % as null.
Result should look like this.
Thanks in advance.
Try This:
INSERT INTO TABLE_NAME SELECT EMPLOYEEDODE, EMPLOYEENAME, 'BENCH' AS PROJECTNAME, NULL AS START_DT, NULL AS ENDDT, SUM(install_capacities), SUM(ActualPercentage) FROM TABLE_NAME GROUP BY EMPLOYEEDODE,EMPLOYEENAME;
Please try the below queries to produce the desired output:
insert into tbl(EmployeeCode, EmployeeName, projectName,ExpectedStartDate, ExpectedEndDate, InstallCapacity, [Actual Allocation Percentage])
select EmployeeCode,EmployeeName,'Bench' As projectName,NULL as ExpectedStartDate, NULL as ExpectedEndDate, SUM(InstallCapacity) as InstallCapacity, SUM([Actual Allocation Percentage]) as [Actual Allocation Percentage]
from tbl
group by EmployeeCode,EmployeeName
select * from tbl order by EmployeeCode,EmployeeName

Select data from one table where a field is greater than that of another field in another table

I want to be able to select data from TableA where Field1 is greater than Field2 in TableB.
In my head i image it to be something like this
Select TableA.*
from TableA
Join TableB
On TableA.PK = TableB.FK
WHERE TableA.Field1 > TableB.Field2
I am using SQL server 2005 and the TableA.Field1 and tableB.Field2 look like:
2004102881010 - data type - Vrachar
My PK and FK look like:
0908232 - data type - nvarchar
The probelm is when this query is ran ALL the data is displaying and not just the rows where Field1 is greater.
Cheers:)
Seems to be working correctly for this demo code. Perhaps I'm not understanding the problem or data.
;
with TABLEA (PK, Field1) AS
(
-- Sample row that is filtered out
SELECT CAST('0908232' AS nvarchar(10)), CAST('2004102881010' AS varchar(50))
-- This is bigger than what's in B
UNION ALL SELECT CAST('0908232' AS nvarchar(10)), CAST('2005102881010' AS varchar(50))
)
, TABLEB(FK, Field2) AS
(
-- This matches row 1 above and will be excluded
SELECT CAST('0908232' AS nvarchar(10)), CAST('2004102881010' AS varchar(50))
)
SELECT TableA.*
FROM TableA
INNER JOIN TableB
ON TableA.PK = TableB.FK
WHERE TableA.Field1 > TableB.Field2
Results
PK Field1
0908232 2005102881010
This seems like a problem with missing zeroes:
20041028*0*81010
There is nothing wrong with your query, but your data.
Consider 2001-01-01 01:01:01, this would be seen as: 200111111
It should be seen as: 20010101010101
Comparrison operators (>, <) used on strings (varchars, nvarchars, etc.) work alphabetically. For example, '9' > '11' is true. You might try doing a data type conversion...
WHERE cast(A.field1 as int) > cast(B.field2 as int)

Resources