Query to find if a column contains both number and decimal only - sql

I have a column to check if contains number from 0-9 and a decimal. Since in the version of SQL am using the below does not seem working
select *
from tablename
whwere columnname like '%[^.0-9]%'
Also tried using column name like '%[0-9]%' and columnname not like '%.%' but if there is a negative sign it is not getting captured. Please advise.
The column data type is float. So can someone provide me a query to check if the column contains values from 0-9 and also it can contain decimal values these two are permitted. If say for example if I have value 9,9.99 ,-1.24 the query should output -1.24 I need this value other than decimal and number –

The issue with your LIKE clause is bad predicate logic ...like '%[^.0-9]%'should be NOT LIKE '%[^0-9.]%'
Take this sample data.
DECLARE #table TABLE (SomeNbr VARCHAR(32));
INSERT #table VALUES ('x'),('0'),('0.12'),('999'),('-29.33'),('88.33.22'),('9-9-'),('11-');
What you were trying to do would be accomplished like this:
SELECT t.someNbr
FROM #table AS t
WHERE someNbr NOT LIKE '%[^0-9.]%';
The problem here is we'll also return "88.33.22" and miss "-29.33", both valid float values. You can handle hyphens by adding a hyphen to your LIKE pattern:
SELECT t.someNbr, LEN(t.SomeNbr)-LEN(REPLACE(t.SomeNbr,'.',''))
FROM #table AS t
WHERE someNbr NOT LIKE '%[^0-9.-]%';
But now we also pick up "9-9-" and stuff with 2+ dots. To ensure that each starts with a number OR a hyphen, to ensure hyphens only exist in the front of the string (if at all) and that we a maximum of one dot:
--==== This will do a good job but can still be broken
SELECT t.someNbr
FROM #table AS t
WHERE someNbr NOT LIKE '%[^0-9.-]%' -- Can only contain numbers, dots and hyphens
AND LEN(t.SomeNbr)-LEN(REPLACE(t.SomeNbr,'.','')) < 2 -- can have up to 1 dot
AND LEN(t.SomeNbr)-LEN(REPLACE(t.SomeNbr,'-','')) < 2 -- can have up to 1 hyphen
AND PATINDEX('%-%',t.SomeNbr) < 2 -- hyphen can only be in the front
This does the trick and returns:
someNbr
--------------------------------
0
0.12
999
-29.33
All that said - **DONT DO THIS ANY OF THIS ^^^ **. There is no need to parse numbers in this way except to show others why not to. I can still break this. They way I return valid floats in a scenario like this is with TRY_CAST or TRY_CONVERT. This returns what you need and will perform better.
--==== Best Solution
SELECT t.someNbr
FROM #table AS t
WHERE TRY_CAST(t.SomeNbr AS float) IS NOT NULL;

Related

Count all elements in an array

I have a table that I save some data include list of numbers.
like this:
numbers
(null)
،42593
،42593،42594،36725،42592،36725،42592
،42593،42594،36725،42592
،31046،36725،42592
I would like to count the number elements in every row in SQL Server
count
0
1
6
4
3
You could use a replacement trick here:
SELECT numbers,
COALESCE(LEN(numbers) - LEN(REPLACE(numbers, ',', '')), 0) AS num_elements
FROM yourTable;
The above trick works by counting the number of commas (assuming your data really has commas as separators). For example, your last sample data point was:
,31046,36725,42592 => length is 18
310463672542592 => length is 15
Hence the difference in lengths correctly yields the right number of elements.
Another idea is to useSTRING_SPLIT:
SELECT y.numbers,
(SELECT COUNT(Value) - 1
FROM string_split(COALESCE(y.numbers,''),',')) AS num_elements
FROM yourtable AS y;
I know this looks a bit unhandy on first glance due to this strange -1 in the second line and the COALESCE in the third line. So why do I talk about this option?
Well, the strange thing in your case which causes these difficulties in my query is that your rows always start with a comma.
This is quite weird and it would be much easier without this first comma in every row.
Let's assume you remove this comma in future. Then this will become really easy and good readable:
SELECT y.numbers,
(SELECT COUNT(Value)
FROM string_split(y.numbers,',')) AS num_elements
FROM yourtable AS y;
Try out: db<>fiddle
your data
CREATE TABLE yourtable(
numbers VARCHAR(max)
);
INSERT INTO yourtable
(numbers) VALUES
(null),
('،42593'),
('،42593،42594،36725،42592،36725،42592'),
('،42593،42594،36725،42592'),
('،31046،36725،42592');
you need ISNULL and len
select
ISNULL(len(numbers) - len(replace(numbers,'،','')) ,0) count
from yourtable
the other way is by using IIF and string_split as follows
SELECT IIF(count < 0, 0, count) count
FROM   (SELECT (SELECT Count(*) - 1
                FROM   STRING_SPLIT (Replace(Replace(numbers, 'R', ''), '،',
                                     'R'), 'R'
                       )) AS
               'count'
        FROM   yourtable) A
dbfiddle

SQL Query to compare the first X characters of 2 fields in a table

Say I have a table named 'Parts'. I am looking to create a SQL query that compares the first X characters of two of the fields, let's call them 'PartNum1' and 'PartNum2'. For example, I would like to return all records from 'Parts' where the first 6 characters of 'PartNum1' equals the first 6 characters of 'PartNum2'.
Parts
PartNum1
PartNum2
12345678
12345600
12388888
12345000
12000000
14500000
the query would only return row 1 since the first 6 characters match. MS SQL Server 2017 in case that makes a difference.
If they are strings, use left():
left(partnum1, 6) = left(partnum2, 6)
This would be appropriate in a where, on, or case expression. Note that using left() would generally prevent the use of indexes. If this is for a join and you care about performance, you might want to include a computed column with the first six characters.
you can try something like this. I am assuming datatype as integer. You can set size of varchar based on length of fields.
select *
from Parts
WHERE SUBSTRING(CAST(PartNum1 AS VARCHAR(max)), 1,6) = SUBSTRING(CAST(PartNum2 AS VARCHAR(max)), 1,6)
You can go for simple division to see if the numerator matches for those partnumbers.
DECLARE #table table(partnum int, partnum2 int)
insert into #table values
(12345678, 12345600)
,(12388888, 12345000)
,(12000000, 14500000);
select * from #table where partnum/100 = partnum2/100
partnum
partnum2
12345678
12345600

Can I combine like and equal to get data?

I have data like this
1234500010
1234500020
1234500021
12345600010
12345600011
123456700010
123456700020
123456710010
The pattern is
1-data(varian 3-7 digit number) + 2-data(any 3 digit number) + 3-data (any 2 digit number)
I want to create SQL to get 1-data only.
For example I want to get data 12345
I want the result only
1234500010
1234500020
1234500021
If I using "like",
select *
FROM data
where ID like '12345%' `
I will get all the data with 12345, 123456 and 1234567
If I using equal, I will only get one specific data.
Can I combine like and equal together to get result like what I want?
select * FROM data where data = '12345 + any 2-data(3 digit) + any 3-data(2 digit)'
Anyone can help?
Addition : Sorry if I didn't mention the data type and make some miss communication. The data type is in char. #Gordon answers and the others not wrong. It works for number and varchar. but not works for char type. Here I post some pic for char data type. Oracle specification for char data type is a fixed lenght. So if I input less than lenght the remain of it will be change into a space.
Thank you very much. Hope someone can help for this
Since your datatype is CHAR, Gordon's answer is not working for you. CHAR adds trailing spaces for the strings less than maximum limit. You could use TRIM to fix this as shown. But, you should preferably store numbers in the NUMBER type and not CHAR or VARCHAR2, which will create other problems sooner or later.
select *
from data
where trim(ID) like '12345_____';
I think you want:
select *
from data
where ID like '12345_____' -- exactly 5 _
Here is a rextester demonstrating the answer.
You really can't combine equality and LIKE. But you can use a regular expression to do this kind of searching, with the REGEXP_LIKE function:
SELECT *
FROM DATA
WHERE REGEXP_LIKE(ID, '^12345[0-9]{3}[0-9]{2}');
But if I understand correctly, for your 1-data you really want a 3 to 7 digit number:
SELECT *
FROM DATA
WHERE REGEXP_LIKE(ID, '^[0-9]{3,7}[0-9]{3}[0-9]{2}');
Oracle regular expression docs here
SQLFiddle here
Best of luck.
I think this gives you the solution you want,
create table data(ID number(15));
insert into data values(1234500010);
insert into data values(1234500020);
insert into data values(1234500021);
insert into data values(12345600010);
insert into data values(12345600011);
insert into data values(123456700010);
insert into data values(123456700020);
insert into data values(123456710010);
select * from data where ID like '12345_____'
// After 5_ underscore are exactly 5 , any 3 digits from 2-data(3 underscores) and 2 digits from 3-data(2 underscores)
You'll be getting(OUTPUT) :
ID
1234500010
1234500020
1234500021
3 rows returned in 0.00 seconds

I am trying to compare two number using Sql query. for e.g 123.45 and 12345 are same if i ignore decimal so it should come in output

I am trying to compare two string using Sql query. for e.g In table A i have A123.45 and in table B i have A12345. this two string are same if i ignore decimal point so as a output i would want table A's value.
First, to avoid the XY problem, it's a little unclear to me why you'd want to do this in the first place - I'm not sure exactly why 123.45 should be equal to 12345. Definitely something to think about.
With that said, if you insist, you can do something like the following:
select case when replace(cast(floatingPointNumber as varchar(50)), '.', '') = cast(yourInteger as varchar(50)) then 1 else 0 end
from YourTable
Obviously, floatingPointNumber is a float and yourInteger is an integer.
I'm not sure what platform you're using since you didn't tag it but I wrote/tested this in SQL Server. You can do something similar in Oracle/MySQL if that's what you're using.
Basically, what this is doing is casting both the floating point number and the integer to strings, removing the decimal from the floating point number, and comparing them. If they're equal, it returns 1; otherwise it returns 0.

select using wildcard to find ending in two character then numeric

I am querying to find things ending in "ST" followed by a number 1 - 999.
SELECT NUMBER WHERE NUMBER LIKE '%ST -- works correctly to return everything ending in "ST"
SELECT NUMBER WHERE NUMBER LIKE '%[1-999] -- works correctly to return everything ending in 1 - 999
SELECT NUMBER WHERE NUMBER LIKE '%ST[1-999] -- doesn't work - returns nothing
Also tried:
SELECT NUMBER WHERE NUMBER LIKE '%ST%[1-999] -- works, but also returns things like "GRASTNT3" that have extra things between the "ST" and the number
Can anyone help this struggling beginner?
Thanks!
The problem is that [1-999] doesn't mean what you think it does.
SQL Server interprets that as a set of values (1-9, 9, 9) which basically means that if there's more than 1 digit after the ST, the entry won't be returned.
So far as I can tell, your best bet is:
SELECT NUMBER WHERE
NUMBER LIKE '%ST[1-9][0-9][0-9]' OR
NUMBER LIKE '%ST[1-9][0-9]' OR
NUMBER LIKE '%ST[1-9]'
(assuming that your numbers don't have leading zeros - if they do, replace the ones with more zeros)
You need to do
SELECT NUMBER WHERE
NUMBER LIKE '%ST[1-9][0-9][0-9]'
OR NUMBER LIKE '%ST[1-9][0-9]'
OR NUMBER LIKE '%ST[1-9]';
The group in the the [] is a Char/NChar not an Int.
Better still normalise and type your data, so you have an ST bit and an int column for the number.
If you find you need to define different filters on variable string data, consider Full Text Searching or another Lucene related technology depending on your RDBMS.