How can I find only one distinct digit in a cell in SQL - sql

I have customer data with mobile phone numbers where '1' has been entered 10 times or more in a cell to bypass the customer onboarding system validation. For example '1111111111'
I used below condition in my where clause but that didn't really help.
AND p.mobile_no LIKE '%[1111111111]%'
It is possible that users might enter 1 multiple number of times in the new customer form to bypass validation. To find only 0 values in the cell I used %[^0]% in the WHERE clause and I was hoping to use something similar to find 1s where regardless of how many times it has been entered in the field, as long as it only has 1 in it it will skim out the data for me.
How can I find these instances in my data using a SQL query?
The goal is to find these anomalies and remove them.
Using: Microsoft SQL Server 2016 (SP2).

I think you are looking for the following, which tests if at least 1 '1' exists, and that no other characters exist.
select Number
from (values ('111'),('121'),('1-2'),('22')) x (Number)
-- Test that at least 1 '1' exists
where Number like '%1%'
-- And that no other allowable characters exist - expand to cover all options
and Number not like '%[0,2-9,-]%'

Using a table to define invalid phone numbers:
Declare #invalidPhoneNumbers Table (PhoneNumber char(10));
Insert Into #testData (PhoneNumber)
Values ('0000000000'), ('1111111111'), ('2222222222'), ('3333333333'), ('4444444444')
, ('5555555555'), ('6666666666'), ('7777777777'), ('8888888888'), ('9999999999');
Select ...
From ...
Where ...
And p.mobile_no Not In (Select i.PhoneNumber From #invalidPhoneNumbers i)
Or - using NOT EXISTS which may perform better:
Declare #invalidPhoneNumbers Table (PhoneNumber char(10));
Insert Into #testData (PhoneNumber)
Values ('0000000000'), ('1111111111'), ('2222222222'), ('3333333333'), ('4444444444')
, ('5555555555'), ('6666666666'), ('7777777777'), ('8888888888'), ('9999999999');
Select ...
From ...
Where ...
And Not Exists (Select * From #invalidPhoneNumbers i Where i.PhoneNumber = p.mobile_no)
When declaring the table - make sure the data type defined matches exactly the defined data type of p.mobile_no. This will make sure there are no implicit conversions that can cause issues.

Related

How to divide the text into two columns by matching text using SQL select query

I have table with a column Note / Reason - like this:
Note / Reason
test
test2
test REASON:ANOTHER PROVIDER
this is a test REASON:NO FITTER
I want to divide the text like below into note and reason like below reason with start with reason and other text will be note
Note Reason
---------------------------------------------------
test
test2'
test REASON:ANOTHER PROVIDER
this is a test REASON:NO FITTER
Using Sean's sample data, as I mentioned in the comments, use CHARINDEX, LEFT and STUFF:
SELECT LEFT(NoteReason,CHARINDEX('REASON:',NoteReason + 'REASON:')-1) AS Note,
STUFF(NoteReason,1,CHARINDEX('REASON:',NoteReason)-1,'') AS Reason
FROM #NoteReason;
Considering you have extra white space, you may also want to wrap the expressions in a TRIM.
It would be better if you provided sample data in a consumable format. That way it is easy for others to use and it is also more precise so others aren't guessing or making assumptions about your tables and sample data. Given the sparse information in your question something like this should be somewhat close.
declare #NoteReason table (NoteReason varchar(100))
insert #NoteReason values
('test')
, ('test2')
, ('test REASON:ANOTHER PROVIDER')
, ('this is a test REASON:NO FITTER')
select Note = case when charindex('REASON', n.NoteReason) = 0 then n.NoteReason
else left(n.NoteReason, charindex('REASON', n.NoteReason) - 1)
end
, Reason = case when charindex('REASON', n.NoteReason) > 0 then substring(n.NoteReason, charindex('REASON', n.NoteReason), len(n.NoteReason)) else '' end
from #NoteReason n

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

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;

String split/chunks into chunked columns from one varchar column

Hopefully everyone is having a productive lockdown all over the world. This is my second issue I wanted some assistance with today.
What I have is a chat from a telecom company signing up new customers.
I have successfully collapsed them into 2x rows per unique_id - a unique chat interaction captured between customer and company agent.
I would like to now take each column (text) in each row and separate
it out to 5 equal varchar columns.
The objective is to splice/chunk a
conversation into 5 different stages within this table.
I do not
have access to delimiters as customers and company staff use
delimiting characters themselves so it makes this tricky.
Below I have 2 images with what the data looks like now and what I am looking for.
BEFORE
AFTER
I have looked at the following articles to try to crack it, but am stuck:
Split A Single Field Value Into Multiple Fixed-Length Column Values in T-SQL
How to Split String by Character into Separate Columns in SQL Server
How to split a comma-separated value to columns
How to split a single column values to multiple column values?
Split string in SQL Server to a maximum length, returning each as a row
Here is the SQL Fiddle page, but I am running this code in MS SQL Server: http://sqlfiddle.com/#!9/ddd08c
Here is the table creation code:
CREATE TABLE Table1
(`unique_id` double, `user` varchar(8), `text` varchar(144))
;
INSERT INTO Table1
(`unique_id`, `user`, `text`)
VALUES
(50314585222, 'customer', 'This is part 1 of long text. This is part 2 of long text. This is part 3 of long text. This is part 4 of long text. This is part 5 of long text.'),
(50314585222, 'company', 'This is part 1 of long text This is part 2 of long text This is part 3 of long text This is part 4 of long text This is part 5 of long text'),
(50319875222, 'customer', 'This is part 1 This is part 2 This is part 3 This is part 4 This is part 5'),
(50319875222, 'company', 'This is part 1 This is part 2 This is part 3 This is part 4 This is part 5')
;
I have requested an almost similar algorithm in R, in my history. I have been trying to do this in SQL.
I have manage to solve this with the T-SQL statement below:
WITH DataSource AS
(
SELECT *
,'\b.{1,'+CAST(CEILING(LEN([text]) * 1.0 /5) AS VARCHAR(12)) +'}\b' AS [pattern]
FROM TAble1
), PreparedData AS
(
SELECT unique_id
,[user]
,'text' + CAST(RM.matchID + 1 AS VARCHAR(12)) as [column]
,RM.CaptureValue AS [value]
FROM DataSource T
CROSS APPLY [dbo].[fn_Utils_RegexMatches] ([text], [pattern]) RM
)
SELECT *
FROM PreparedData DS
PIVOT
(
max([value]) for [column] IN ([text1], [text2], [text3], [text4], [text5])
) PVT;
In order to use this code, you need to implement SQL CLR function(s) for working with regular expression in the context of T-SQL (you need to invest some time understanding how SQL CLR works) - otherwise, you will not be able to use this solution.
So, having RegexMatches function, the first part is to build a regular expression pattern for splitting the data:
SELECT *
,'\b.{1,'+CAST(CEILING(LEN([text]) * 1.0 /5) AS VARCHAR(12)) +'}\b' AS [pattern]
FROM TAble1;
The pattern is \b.number\b and will match part of the strings with length number but not cutting the words (check if boundary works for you, because in some cases it won't).
Then, using our regex matches function we getting a result like this (the second common table expression):
And the data above is ready for pivoting which is pretty easy.
So, the notes are:
you need to implement Microsoft String Utility
you need to ensure the regex pattern works for you
you can split the T-SQL I used, check the other columns of the regex function and even make dynamic pivoting - the code is an example and need to modify/check it before using in production

Hard request SQL Server 2008

I have a pretty hard request to do in SQL Server 2008, but I'm not able to do the whole...
I have two kind of records :
16HENFC******** (8 numbers after more 'FC')
16HEN******* (7 numbers after more 'EN')
I have to select the * (which are in fact numbers), and add a 0 at the beginning of the second form of record to just have 8 long selected values.
Then I have to insert the result in a empty table.
I think I did the first part which is :
SUBSTRING(SELECT mycolumn1 FROM mytable1 WHERE mycolumn1 LIKE '16HENFC%', 5, 8) ;
In summary,
I have those records in my column :
'16HENFC071052'
'16HEN5130026'
I want to select them and transform them to insert those ones in an other column :
'05130026'
'FC071052'
[EDIT]=>
CREATE TABLE nom_de_la_table
(
colonne1 VARCHAR(250),
colonne2 VARCHAR(250)
)
INSERT INTO nom_de_la_table (colonne1)
VALUES
('16HEN5138745'),
('16HENFC071052v2'),
('16HENFC78942878'),
('16HEN4830026'),
('16HEN7815934'),
('16HENFC74859422'),
('16HEN9687326'),
('16HENFC74889639'),
('16HEN9798556');
[etc...]
So two different types of records, and I want to insert the result of what you did first with just two records in an other column but for the 956 records of my table. And this is the result with the two examples :
'05130026'
'FC071052'
Left-Filling a string is a relatively easy request. Here's an example:
select right(replicate('0',8) + right(test,len(test)-len('16HEN')),8)
from (
select '16HENFC071052' as test
union all
select '16HEN5130026' as test
) z
Use replicate to left-fill your string with the amount of digits you wish to end up with. Append your desired string, in this case, slice your prefix off by taking the right X characters where X = len(target) - len(prefix). Finally, take the right characters of the whole string equal to your desired length.

add record in SQL based on last character of a field

I have a field in sql that contains a 1 or 0 at the end. What I am trying to do is if the field has a 1 at the end but no corresponding 0 I would like to add that record.
3 different examples
Field value
Data1 ( I would like to add another record containing Data0)
Data0 ( I would like to add another record containing Data1)
Data0 and Data1 both exists in table ( Do nothing )
insert into test(col, another_column_1,...,another_column_n)
select substr(col,1, length(col)-1) || --this is the base value
max(mod(substr(col,length(col),length(col))+1,2)) --this is the termination (0 or 1)
as col ,
max(another_column_1),
...
max(another_column_n)
from test
where substr(col,length(col),length(col)) between '0' and '1'
group by substr(col,1, length(col)-1)
having count(*)=1;
you can see test here
Updated for Oracle
If I understood your question correctly, you can use the LIKE operator.
You can do something like:
(field like '%1' or field like '%0') and not field like '%0%1'
But generally, SQL is not suitable for text processing. This LIKE thing is pretty much the most advanced text processing feature in SQL.