ACCESS Jet SQL INT() Function -> SQL Server Function - sql

I am converting an Access Jet-SQL query into T-SQL and I came upon the Int() function. Now, I would like to convert it into T-SQL, and this is what I have so far:
--Works for Positive
Select CONVERT(INT, 1.2)
--Answer = 1
--Not the same as Access
SELECT CONVERT(INT, -1.2)
--Answer = -1
Now, according to this, I need it to return -2, not -1. Does anyone have cleaner T-SQL code than:
DECLARE #test FLOAT
SET #test = -1.2
SELECT CASE WHEN #test < 0 THEN CONVERT(INT, #test) - 1 ELSE CONVERT(INT, #test) END
Can anyone come up with cleaner code than this (T-SQL only)? No UDFs as this is an adhoc query. Thanks!

SELECT FLOOR(#test)

Oh yeah...
select convert(int, floor(#test))
Never mind...

Related

Calculate string from field in temporary table select using sp_executesql

I've got a temporary table which I can select out of as follows:
select
testId
,testoutput
from
#testResults
This yields results such as the following:
ID Result
1 4303
2 -150000*200*3= -90000000
3 4.2016
4 3205000
The second value is due to some of our tests outputting the calculation rather than value for readability in later reports.
I'd like to turn that calculation back into a number, which I believe is doable via sp_executesql...
I've changed my select to:
select
testId
,case
WHEN isnumeric(trim(testoutput)) = 1 THEN pr.expectedOutput
WHEN CHARINDEX('=', testoutput) != 0 then
exec sp_executesql N'rtrim(left(testoutput, CHARINDEX(''='', testoutput) - 1))'
END
from
#testOuput
i.e. when there's an "=" sign, then split off what's the left of the sign and try to exec sp_executesql on it.
This throws all sorts of syntax errors, which I can't get my head around.
I'd really appreciate any help with the syntax of the sp_executesql
You can also extract the result of the calculation:
SQL Server without TRIM or TRY_PARSE
SELECT testId, CASE
WHEN ISNUMERIC(LTRIM(RTRIM(testoutput))) = 1 THEN pr.expectedOutput
WHEN CHARINDEX('=', testoutput) > 0 THEN
LTRIM(RTRIM(RIGHT(testoutput, CHARINDEX('=', REVERSE(testoutput))-1)))
END
FROM #testOuput
SQL Server with TRIM and TRY_PARSE
SELECT testId, CASE
WHEN TRY_PARSE(TRIM(testoutput) AS NUMERIC) IS NOT NULL THEN pr.expectedOutput
WHEN CHARINDEX('=', testoutput) > 0 THEN
TRIM(RIGHT(testoutput, CHARINDEX('=', REVERSE(testoutput))-1))
END
FROM #testOuput
demo on dbfiddle.uk

how to handle divide by zero error in sql

cast(CAST(countAta AS float)
/ CAST(DATEDIFF(day,#searchDate,#EndDate) AS float) as decimal(16,2)
)
You can avoid such situations by setting the following parameters before your query and it should work just fine.
SET ARITHABORT OFF
SET ANSI_WARNINGS OFF
This would return a NULL when you do something like this: 123 / 0
The important point is to set these properties back ON once you are done with such operations. This particularly helps when you have complex queries in your Stored procedure and you don't want to end up writing more and more CASE statements to handle such a situation.
You should always use TRY-CATCH block and use the built-in error handling functions provided by SQL. Also, you can handle it in another way --
SELECT CASE
WHEN (CAST(DATEDIFF(Day, #searchDate, #EndDate) AS FLOAT) AS DECIMAL(16, 2)) = 0
THEN NULL -- Ideally it should return NULL but you can change it as per your requirement
ELSE CAST(CAST(Counter AS FLOAT) / CAST(DATEDIFF(Day, #searchDate, #EndDate) AS FLOAT) AS DECIMAL(16, 2))
END
The best way is NULLIF() . . . but you can't turn the value back into a 0:
select CAST(CAST(countAta AS float) /
NULLIF(DATEDIFF(day, #searchDate, #EndDate), 0
) as decimal(16, 2)
)
This returns NULL if the denominator is 0. Note that you don't have to cast to a float twice.
You could use NULLIF to avoid devided by zero error.
It returns NULL when denominator equals 0
CAST(countAta AS decimal(16,2)) /ISNULL(NULLIF(DATEDIFF(day,#searchDate,#EndDate),0), 1)
Or use CASE WHEN
CAST(countAta AS decimal(16,2)) /
CASE WHEN DATEDIFF(day,#searchDate,#EndDate) = 0 THEN 1
ELSE DATEDIFF(day,#searchDate,#EndDate)
END

Remove only zero after decimal sql server 2012

Consider the following numbers.
7870.2
8220.0
I need to remove decimal points if the value ends with .0. If it ends with .2 then it should keep the value as it is.
I have used ceiling but it removes all the values after decimal.
How can I write a select query in which I can add some condition for this?
Generally speaking you should not do this in your dB. This is an app or reporting side operation. The dB is made to store and query information. It is not made to format/string manipulate information.
use right within a case statement and:
DECLARE #val decimal(5,1)
SET #val = 7870.0
Select
Case
When right(#val,1)<> '0' then
cast(#val as varchar)
else
cast(cast(#val as int) as varchar)
End
output: 7870
EDIT: I could write :
Case
When right(#val,1)<> '0' then
#val
else
cast(#val as int) -- or floor(#val)
End
but because return type of case statement is the highest precedence type from the set of given types, so the output for second version is: 7870.0 not 7870, that's why I convert it to i.e varchar in when clauses, and it can be converted outside of case statement, I mean cast ((case when...then...else... end) as datatype)
Cast the number as a float, using float(24) to increase precision:
DECLARE #t table(number decimal(10,1))
INSERT #t values(7870.2),(8220.0)
SELECT cast(number as float(24))
FROM #t
Result:
7870,2
8220
Here below goes a sample:
declare #1 decimal(4,3)
select #1 = 2.9
select case when SUBSTRING (PARSENAME(#1,1), 1, 1) = 0 then FLOOR(#1) else #1 end
Change the #1 in the select statement with your database field name.
sqlfiddle
The solution seems to be simple:
SELECT CONVERT (FLOAT, PAYLOAD)

SQL IsNumeric not working

The reserve column is a varchar, to perform sums on it I want to cast it to a deciaml.
But the SQL below gives me an error
select
cast(Reserve as decimal)
from MyReserves
Error converting data type varchar to numeric.
I added the isnumeric and not null to try and avoid this error but it still persists, any ideas why?
select
cast(Reserve as decimal)
from MyReserves
where isnumeric(Reserve ) = 1
and MyReserves is not null
See here: CAST and IsNumeric
Try this:
WHERE IsNumeric(Reserve + '.0e0') = 1 AND reserve IS NOT NULL
UPDATE
Default of decimal is (18,0), so
declare #i nvarchar(100)='12121212121211212122121'--length is>18
SELECT ISNUMERIC(#i) --gives 1
SELECT CAST(#i as decimal)--throws an error
Gosh, nobody seems to have explained this correctly. SQL is a descriptive language. It does not specify the order of operations.
The problem that you are (well, were) having is that the where does not do the filtering before the conversion takes place. Order of operations, though, is guaranteed for a case statement. So, the following will work:
select cast(case when isnumeric(Reserve) = 1 then Reserve end as decimal)
from MyReserves
where isnumeric(Reserve ) = 1 and MyReserves is not null
The issue has nothing to do with the particular numeric format you are converting to or with the isnumeric() function. It is simply that the ordering of operations is not guaranteed.
It seems that isnumeric has some Problems:
http://www.sqlhacks.com/Retrieve/Isnumeric-problems
(via internet archive)
According to that Link you can solve it like that:
select
cast(Reserve as decimal)
from MyReserves
where MyReserves is not null
and MyReserves * 1 = MyReserves
Use try_cast (sql 2012)
select
try_cast(Reserve as decimal)
from MyReserves
IsNumeric is a problem child -- SQL 2012 and later has TRY_CAST and TRY_CONVERT
If you're on an earlier version then you can write a function that'll convert to a decimal (or NULL if it won't convert). This uses the XML conversion functions that don't throw errors when the number won't fit ;)
-- Create function to convert a varchar to a decimal (returns null if it fails)
IF EXISTS( SELECT * FROM sys.objects WHERE object_id = OBJECT_ID( N'[dbo].[ToDecimal]' ) AND type IN( N'FN',N'IF',N'TF',N'FS',N'FT' ))
DROP FUNCTION [dbo].[ToDecimal];
GO
CREATE FUNCTION ToDecimal
(
#Value VARCHAR(MAX)
)
RETURNS DECIMAL(18,8)
AS
BEGIN
-- Uses XML/XPath to convert #Value to Decimal because it returns NULL it doesn't cast correctly
DECLARE #ValueAsXml XML
SELECT #ValueAsXml = Col FROM (SELECT (SELECT #Value as Value FOR XMl RAW, ELEMENTS) AS Col) AS test
DECLARE #Result DECIMAL(38,10)
-- XML/XPath will return NULL if the VARCHAR can't be converted to a DECIMAL(38,10)
SET #Result = #ValueAsXml.value('(/row/Value)[1] cast as xs:decimal?', 'DECIMAL(38,10)')
RETURN CASE -- Check if the number is within the range for a DECIMAL(18,8)
WHEN #Result >= -999999999999999999.99999999 AND #Result <= 999999999999999999.99999999
THEN CONVERT(DECIMAL(18,8),#Result)
ELSE
NULL
END
END
Then just change your query to:
select dbo.ToDecimal(Reserve) from MyReserves
isnumeric is not 100% reliable in SQL - see this question Why does ISNUMERIC('.') return 1?
I would guess that you have value in the reserve column that passes the isnumeric test but will not cast to decimal.
Just a heads up on isnumeric; if the string contains some numbers and an 'E' followed by some numbers, this is viewed as an exponent. Example, select isnumeric('123E0') returns 1.
I had this same problem and it turned out to be scientific notation such as '1.72918E-13' To find this just do where Reserve LIKE '%E%'. Try bypassing these and see if it works. You'll have to write code to convert these to something usable or reformat your source file so it doesn't store any numbers using scientific notation.
IsNumeric is possibly not ideal in your scenario as from the highlighted Note on this MSDN page it says "ISNUMERIC returns 1 for some characters that are not numbers, such as plus (+), minus (-), and valid currency symbols such as the dollar sign ($)."
Also there is a nice article here which further discusses ISNUMERIC.
Try (for example):
select
cast(Reserve as decimal(10,2))
from MyReserves
Numeric/Decimal generally want a precision an scale.
I am also facing this issue and I solved by below method. I am sharing this because it may helpful to some one.
declare #g varchar (50)
set #g=char(10)
select isnumeric(#g),#g, isnumeric(replace(replace(#g,char(13),char(10)),char(10),''))

Equivalent to VB AndAlso in SQL?

Is there an equivalent to VB's AndAlso/OrElse and C#'s &&/|| in SQL (SQL Server 2005). I am running a select query similar to the following:
SELECT a,b,c,d
FROM table1
WHERE
(#a IS NULL OR a = #a)
AND (#b IS NULL OR b = #b)
AND (#c IS NULL OR c = #c)
AND (#d IS NULL OR d = #d)
For example, if the "#a" parameter passed in as NULL there is no point in evaluating the 2nd part of the WHERE clause (a = #a). Is there a way to avoid this either by using special syntax or rewriting the query?
Thanks,
James.
The only way to guarantee the order of evaluation is to use CASE
WHERE
CASE
WHEN #a IS NULL THEN 1
WHEN a = #a THEN 1
ELSE 0
END = 1
AND /*repeat*/
In my experience this is usually slower then just letting the DB engine sort it out.
TerrorAustralis's answer is usually the best option for non-nullable columns
Try this:
AND a = ISNULL(#a,a)
This function looks at #a. If it is not null it equates the expression
AND a = #a
If it is null it equates the expression
AND a = a
(Since this is always true, it replaces the #b is null statement)
The query engine will take care of this for you. Your query, as written, is fine. All operators will "short circuit" if they can.
Another way is to do:
IF (#a > 0) IF (#a = 5)
BEGIN
END
Another if after the condition will do an "AndAlso" logic.
I want to emphesise that this is just a short way to write:
IF (#a > 0)
IF (#a = 5)
BEGIN
END
Take this example:
SELECT * FROM Orders
WHERE orderId LIKE '%[0-9]%'
AND dbo.JobIsPending(OrderId) = 1
Orders.OrderId is varchar(25)
dbo.JobIsPending(OrderId) UDF with int parameter
No short circuit is made as the conversion fails in dbo.JobIsPending(OrderId) when
Orders.OrderId NOT LIKE '%[0-9]%'
tested on SQL Server 2008 R2