SQL Search a Numeric Field for non whole numbers - sql

I have a DB that has a numeric field and I need to search all the rows and return only the non whole numbers.
I have tried the query below and it keeps retuning records that have 0.
SELECT
li.QTY
FROM
TABLE LI
WHERE
li.QTY like '%.%'

You can use LIKE only with char fields, not with number (integer or float) ones.
If by "whole numbers" you mean 0.0 , 2.0 , -5.0 , etc. and not 12.5 , 0.67 then this can do:
SELECT li.QTY
FROM TABLE LI
WHERE li.QTY != ROUND(li.QTY , 0)
;
(for SQL-Server: edited the TRUNC into ROUND)
You could also use the FLOOR or CEILING functions:
SELECT li.QTY
FROM TABLE LI
WHERE li.QTY != FLOOR(li.QTY)
;

Why it does not work. When QTY is a numeric column, when you display it, or implicitly convert to varchar (LIKE does it implicitly), ALL numbers will be cast to the same number of decimal places.
Consider this SQL statement
with TBL(qty) as (select 1.1 union all select 3)
SELECT li.QTY FROM TBL LI WHERE li.QTY like '%.%'
Output
1.1
3.0 << this contains "." even if it does not need to
Cast it to a bigint and it will drop any decimals, then compare it again.
SELECT li.QTY FROM TBL LI
WHERE li.QTY <> CAST(qty as bigint)
If you MUST use LIKE (or just for show..)
SELECT li.QTY, CONVERT(varchar, li.qty)
FROM TBL LI
WHERE li.QTY LIKE '%.%[^0]%'

--Most Def...Cast as an int...Save you from validation of anything. Especially for conversions of dates into a whole date since Microsoft does not like a round down date function.
--For example:
--For every 300 hours an employee works they receive 1 whole day of vacation
--partial days of vacation will not be counted
Declare
#SumHours as decimal(38,10),
#VacationValidation as int
Set #SumHours = 3121.30000000000000000000
Set #VacationValidation = 300
Select cast(((#SumHours)/(#VacationValidation)) as int)
Select day(((#SumHours)/(#VacationValidation))) -1
--without casting as an int, I would need to validated the Day function to make sure that I'm not
--offsetting a whole day by one day.

CAST function work for me.
SELECT li.QTY FROM TABLE LI WHERE li.QTY != CAST(li.QTY AS INTEGER)

DECLARE #Value AS float
SET #Value = 250.00
CASE WHEN CHARINDEX('.',(CAST(b.Value/#Value as char))) = 0 THEN 'WholeNumber' ELSE 'Fraction' END AS mResult

Related

Filter IDs with just numbers excluding letters

So I have results that begins with 2 letters followed by 3 numbers, for example:
ID_Sample
AB001
BC003
AB100
BC400
How can I do a query that ignores the letters and just looks up the numbers to do a filter? For example:
WHERE ID_Sample >= 100
I tried using a "Replace" to get rid of known letters, but I figured there might be a better way. For example:
Select
Replace(id_sample,'AB','')
Choosing the 3 numerals on the right would work too.
For your sample data, you can just start at the third character and convert to a number:
where try_convert(int, stuff(ID_Sample, 1, 2, '')) > 100
Or, if you know that the number is 3 characters:
where try_convert(int, right(ID_Sample, 3)) > 100
+1 for Gordon's answer. This is a fun problem that you can solve using TRANSLATE if you're using SQL 2017+.
First, in case you've never used it, Per BOL TRANSLATE:
Returns the string provided as a first argument after some characters
specified in the second argument are translated into a destination set
of characters specified in the third argument.2
This:
SELECT TRANSLATE('123AABBCC!!!','ABC','XYZ');
Returns: 123XXYYZZ!!!
Here's the solution using TRANSLATE:
-- Sample Data
DECLARE #t TABLE (ID_Sample CHAR(6))
INSERT #t (ID_Sample) VALUES ('AB001'),('BC003'),('AB100'),('BC400'),('CC555');
-- Solution
SELECT
ID_Sample = t.ID_Sample,
ID_Sample_Int = s.NewString
FROM #t AS t
CROSS JOIN (VALUES('ABCDEFGHIJKLMNOPQRSTUVWXYZ', REPLICATE(0,26))) AS f(S1,S2)
CROSS APPLY (VALUES(TRY_CAST(TRANSLATE(t.ID_Sample,f.S1,f.S2) AS INT))) AS s(NewString)
WHERE s.NewString >= 100;
Without the WHERE clause filter you get:
ID_Sample ID_Sample_Int
--------- -------------
AB001 1
BC003 3
AB100 100
BC400 400
CC555 555
... the WHERE clause filters out the first two rows.
Check these methods- Unit test also done!
Declare #Table as table(ID_Sample varchar(20))
set nocount on
Insert into #Table (ID_Sample)
Values('AB001'),('BC003'),('AB100'),('BC400')
--substring_method
select * from #Table
where try_cast(substring(ID_Sample,3,3) as int) >100
--right_method
select * from #Table
where try_cast(right(ID_Sample,3) as int) >100
--stuff_method
select * from #Table
where try_cast(stuff(ID_Sample,1,2,'') as int) >100
--replace_method
select * from #Table
where try_cast(replace(ID_Sample,left(ID_Sample,2),'') as int) >100

SQL How to convert number to text with minimum decimal places (dynamic number of decimal places) in SQL

In an SQL query, I want to convert numeric value to text with minimum no. of decimal places, example if the number is 2.50, then I want output as 2.5; if number is 3, then I want output as 3; if number is 18.75, I want output as 18.75, etc.
How can I achieve this?
EDIT 1:
To give more background, I am dividing 2 numeric values, and want the result in text with minimum required decimal places.
Thanks.
In SQL 2012 and above you can write
SELECT FORMAT(15.0/4.0 , '#.########' )
It uses FORMAT function which uses .NET String.Format functionality.
If want to get 2 decimals for division values, use this
Select case when right(cast ( x/y as decimal(18,2)),1) = 0
then left (cast ( x/y as decimal(18,2)),3)
else cast ( x/y as decimal(18,2)) end ReqOutput
This should do the trick...
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
SomeNumber DECIMAL(9,7) NOT NULL
);
INSERT #TestData (SomeNumber) VALUES
(1.2345670), (1), (99.00100), (5.55);
SELECT
td.SomeNumber,
REVERSE(STUFF(rcv.RevCastVarchar, 1, PATINDEX('%[^0.]%', rcv.RevCastVarchar) - 1, ''))
FROM
#TestData td
CROSS APPLY ( VALUES (REVERSE(CAST(td.SomeNumber AS VARCHAR(10)))) ) rcv (RevCastVarchar);
HTH,
Jason

How to auto generate a ID with random numbers in sql server

For example I had a column named 'ID'
I want to get the output as
ID
---
ABCXX708
ABCXX976
ABCXX654
ABCXX081
In short ABCXX should be common for every row but the remaining 3 numbers should be random and integer..
with t (n) as (select 0 union all select n+1 from t where n <100)
select 'ABC'
+ format(n,'00')
+ cast(cast(rand(cast(newid() as varbinary(100)))*10 as int) as char(1))
from t
Alternative solution
with t (n) as (select 0 union all select n+1 from t where n <100)
select 'ABC'
+ right ('0' + cast(n as varchar(2)),2)
+ cast(cast(rand(cast(newid() as varbinary(100)))*10 as int) as char(1))
from t
You can write like this
select 'ABCXX'+CAST(FLOOR(RAND()*(1000-100)+100) as varchar(3)) 'id'
With the RAND() function you can get Random numbers. And For the 'ABCXX' you can follow your previous logic.
SELECT CAST(RAND()*10.00 AS INT)
The above RAND() function will give values between 0.0 to 1.0 in decimals every time you hit the Statement. To make it for a single digit Multiply with 10 and Cast it to INT to remove the next decimal values.
Reference " MSDN
Since SQL Server 2012 you have FORMAT function and SEQUENCE object. Hence the below query will work.
First you need to create a Sequence object.
CREATE SEQUENCE DemopSeq
START WITH 1
INCREMENT BY 1;
Then the following query will generate results as per your requirement.
SELECT CONCAT('ABC',FORMAT(NEXT VALUE FOR DemopSeq, '00'),ABS(Checksum(NewID()) % 10))
Hope this helps.

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)

Remove trailing zero from decimal number

I have a one database table field called Amount which type is decimal(18,6). so it is stored in database up to 6 decimal points like 9.786534 But while retrieving that field using select query i have to take care like following
Remove trialling zero e.g if number is 9.230000 then result is only 9.23
If decimal points are all zero then only remove only four trialling zero e.g If number is 9.000000 then result is 9.00
Result is up to 2 decimal point if there are trialling zero.
If we write simple query like
select TOP 1 Amount From EmployeeMaster
then it gives 9.230000
but my intension is to remove trailing zero..
Please help me..
It works for removing trailing zeros, but I am still not able to convert 9 to 9.00 in this method.
Declare #myvalue varchar(50),
#Price Varchar(50)
Set #Price = '9.230000'
set #Myvalue = reverse(substring(#Price,patindex('%.%',#Price)+1,len(#Price)))
SELECT
case
When patindex('%.%[1-9]%',#price) = 0 Then
substring(#price,1,patindex('%.%',#price)-1)
else
substring(#price,1,patindex('%.%',#price)-1) + '.' + Reverse(substring(#Myvalue,patindex('%[1-9]%',#Myvalue),len(#Myvalue)))
END
Coming from decimal(18,6) you could do...
select cast(Amount as decimal(18,2))
Most databases that support the CAST function will round the number while converting it. On SQLServer this is what I would do if I wanted rounding.
If what you actually want is a string with only two digits after the decimal then you could
select cast((Amount as decimal(18,2)) as nvarchar)
nvarchar is SQLServer's variable length unicode type. Databases do not agree much on string types. Your database may have a different one. The rest of that sql is ANSI standard. Not all dbs support that either but many do.
This should work
SELECT CAST(REPLACE(RTRIM(REPLACE(CAST(CAST(33.9082976 AS DECIMAL(38,8)) AS NVARCHAR(256)),'0',' ')),' ','0') AS FLOAT)
Does this work?
select TOP 1 ROUND(Amount, 2) From EmployeeMaster
TRY below mentioned code.
SELECT TOP 1 CONVERT(DECIMAL(10,2),Amount) From EmployeeMaster
Hope it will work as expected.
An alternative approach:
1) convert the decimal to a string;
2) split the string into 2 parts, separating the last 4 characters from the rest of the string;
3) remove trailing zeros from the last 4 characters;
4) concatenate the two parts back.
WITH data (V) AS (SELECT CAST(9.786534 AS decimal(18,6))
UNION ALL
SELECT CAST(9.78653 AS decimal(18,6))
UNION ALL
SELECT CAST(9.7800 AS decimal(18,6))
UNION ALL
SELECT CAST(9.7 AS decimal(18,6))
UNION ALL
SELECT CAST(9.00000 AS decimal(18,6))
)
, AsString (V) AS (SELECT CAST(V AS varchar) FROM data)
, Split (L, R) AS (SELECT LEFT(V, LEN(V) - 4), RIGHT(V, 4) FROM AsString)
, Adjusted AS (SELECT L,
REPLACE(RTRIM(REPLACE(R, '0', ' ')), ' ', '0') AS R
FROM Split)
SELECT Result = L + R FROM Adjusted
The output of the above script is:
Result
--------
9.786534
9.78653
9.78
9.70
9.00
I guess using patindex in your case:
CASE WHEN FLOOR(Amount) <> CEILING(Amount) THEN
LTRIM(SUBSTRING(STR(Amount, 18, 6), 1, LEN(STR(Amount, 18, 6)) - PATINDEX('%[^0]%', REVERSE(str(Amount, 18, 6))) + 1))
ELSE STR(Amount,18,2)
END
for a decimal(18,6) field this should work:
select trim(to_char(Amount, '999999999999999999.99')) from EmployeeMaster
(at least for Oracle, not sure about other types)