How to display phone numbers in SQL that contain two and only two '0s'? - sql

I am trying to write a query that will extract phone numbers from a column that are formatted in a particular manner. This format is causing me to run into some problems on how to extract the numbers I need.
Some context: I have a table called Suppliers and a column called Phone. An example phone number would be: (010) 9984510. The area codes are all enclosed in parentheses. There are several phone numbers in the column with a similar format. I need to extract the phone numbers that contain two AND ONLY two '0s' in them. Here is what I tried:
select SupplierID, Phone
from Suppliers
where Phone like '%0%0%';
SupplierID is just a column with an ID number. The main problem I am facing is how can I extract those numbers with two and only two '0s'? The parentheses are causing me to extract more numbers than needed. I do not believe I am allowed to edit the column in any way, but any solution is welcome.

Use like and not like:
where Phone like '%0%0%' and Phone not like '%0%0%0%'

You could use replace() and len():
where len(phone) - len(replace(phone, '0', '')) = 2

For "giggles", you could take a very different approach and count the 0 characters:
SELECT YT.*
FROM dbo.YourTable YT
CROSS APPLY (SELECT COUNT(V.C) AS Zeroes
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15))T(I) --I doubt a phone number will be over 15 characters long
CROSS APPLY (VALUES(SUBSTRING(YT.Phone,T.I,1)))V(C)
WHERE V.C = '0') Z
WHERE Z.Zeroes = 2;

If you want to ignore the area code
where phone like '%)%0%0%' and phone not like '%)%0%0%0%'

Related

Create a new row when encountering a special character (eg "/") in a field

I'm trying to replicate a record whenever I come across a slash in a specific field.
Background of the problem: I'm trying to compare two lists of data containing item number, item description, and item serial number. One list has item quantity and status information, the other list has item location information, so I'm trying to match up the location list onto the main list. The problem is that both lists were created independently of each other so they both have errors and I've only been able to inner join in SQL about 20%. The rest don't match up because the item number is wrong in one list or the other, the serial number might be missing a digit in one list, and I can't compare the nomenclatures very well either because one might say "Hand Wrench" and the other might say "Wrench, 5mm, socket".
Additionally, one list of data has multiple items, that related to some main item, saved in each record. They did this by storing the multiple serial numbers separated by slashes in the serial number field.
Tried using Levenshtein difference (fuzzy match) in Alteryx for serial number / item number matching. This created way too many false positives because serial numbers are sequential, item numbers are frequently incorrect, and item descriptions might look similar to a human but character length can be wildly different (eg. "Truck" in one list might not match well if the other list has something like "Truck, 8 wheel, cargo, flatbed").
I'm currently trying to just match the lists on if the serial number in one list is contained in the other list (with multiple serial numbers in the serial number field).
Example SQLite code I'm currently using
select * from [MISSING ITEMS LIST] as a
left join [RFID TAG SCAN] as b on
b.[SERIAL NUMBER] like '%' || (a.[SERIAL NUMBER] || '%')
where b.[SERIAL NUMBER] <> '' and b.[SERIAL NUMBER] is not null
What I'm trying to achieve:
Recopying this part from above:
So table A might have this:
Record# Item# Description SN
1, 156928, Truck, 1234
2, 209344, Truck Cover, 5588
And Table B might have this
Record# Item# Description SN
1, 156928, Truck, 5588/01234
To make the analysis a little easier, I'd like to convert Table B to this:
Record# Item# Description SN
1, 156928, Truck, 5588
1, 156928, Truck, 01234
If I assume there is at most one slash, then in MariaDB you can do:
select Record, Item, Description
substring_index(SN, '/', 1) as SN
from t
union all
select Record, Item, Description
substring_index(SN, '/', -1) as SN
from t
where SN like '%/%';
In order to convert table B to the format you want use the Text to Columns tool
In the Configuration, set the Delimiter to "/" and select "Split to Rows"

Join on phone numbers in different formats

I need an oracle SQL join on two tables on fields with phone numbers that have different formats. The field on one table is the format 555-555-5555 and the other (555) 555-5555.
What is the syntax that could make this work? The tables are small enough I could probably get by with dropping area codes and just focus on the last 4 digits.
Is it possible? If I can't do a join I'm curious of the syntax for a simple compare such as: Where last4(phonenumber) = '4567'
If you want to compare the whole number, you can probably user regexp_replace to keep only the digits and then do the comparison:
where regexp_replace(phone_number,'\D','') = '55555551234';
\D matches non-digit character and removes them.
If last 4 digits will do, you can use substr:
where substr(phone_number,-4) = '1234';
Basically, you can use any string function on your join (in the ON clause, it doesn't have to be straight forward columns, can be calculated values).
For example, following what you suggested, you can use SUBSTR to get the last four digits, and use this on your join:
SELECT * from tableA INNER JOIN tableB on SUBSTR(tableA.num,-4,4) = SUBSTR(tableAB,-4,4)

Search a column for values LIKE in another column

I searched but couldn't find what I was looking for, maybe I'm not looking for the right terms though.
I have a colum for SKUs and a Keyword column, the SKUs are formatted AA 12345, and the Keywords are just long lists of words, what I need to do is find any records where the numbers in the SKU match any part of the Keywords, I'm just not sure how to do this. For example I'd like to remove the AA so that I'm looking for %12345% anywhere inside of the value of keywords, but I need to do it for every record.
I've tried a few variations of:
SELECT *, Code AS C
FROM Prod
WHERE Keywords LIKE '%C%';
but I get errors on all of them. Can someone help?
Thank you.
EDIT: Okay, sorry about that, the question wasn't the clearest. I'll try to clarify;
The SKU column has values that have a 2 letter prefix in front of a varying amount of numbers such as, AA 12345 or UN 98767865
The Keywords columns are full of information, but also include the SKU values, the problem here is that some of the keyword columns contain the SKU values of products that have entirely different records
I'm trying to find what columns contain the value of different records.
I hope that's more understandable.
EDIT EDIT: Here is some actual sample data
Code: AD 56409429
Keywords: 56409429, 409249, AD 56409429, AD-56409429, Advance 56409429, Nilfisk 56409429, Nilfisk Advance 56409429, spx56409429, 56409429M, 56409429G, 56409429H, ADV56409429, KNT56409429, Kent 56409429, AA 12345
Code: AA 12345
Keywords: AA 12345, 12345, Brush
I need to find all the records where an Errant Code value has found it's way into the Keywords, such as the first case above, so I need a query that would only return the first example
I'm really sorry my explanation is confusing, it's perhaps an extension of how confused I am trying to figure out how to do it. Imagine me sitting there with the site owner who added thousands of these extra sku numbers to their keywords and having them ask me to then remove them :/
Assuming all of your SKU values are in exactly the same format you can remove the 'AA' part using SUBSTRING and then use the result in the LIKE statement:
SELECT * FROM Prod WHERE Keywords LIKE '%' + SUBSTRING(Code, 3,5) + '%'
Seeing as your SKU codes can be variable length the SUBSTRING statement above will have to changed to:
SELECT * FROM Prod WHERE Keywords LIKE '%' + SUBSTRING(Code, 3, LEN(Code)) + '%'
This will remove the first 3 characters from your SKU code regardless of the number of digits it contains afterwards.
It is not entirely clear from your question whether or not the Keywords are in the format AA 12345 or just 12345 but assuming they are and are comma separated. Then you can find all records where the code is in the keywords but there are OTHER keywords also by using this statement:
SELECT *
FROM Prod
WHERE Keywords LIKE '%' + SUBSTRING(Code, 3, LEN(Code)) + '%'
AND Keywords <> SUBSTRING(Code, 3, LEN(Code))
This statement basically says find me all records where SKU code is somewhere in the Keywords BUT also must not exactly match the Keywords contents, i.e. there must be other keywords in the data.
Ok based on your last revisions I think this will work - or at least get you along the road (I am assuming your Product table has a primary key of Id). Also this is most likely horribly inefficient but seeing as it sounds as if this is a one off tidy up it may not matter too much as long as it works (at least that is what I am hoping).
SELECT DISTINCT P.Id
FROM PROD P
INNER JOIN
(
-- Get all unique SKU codes from Prod table
SELECT DISTINCT SUBSTRING(CODE, 3, LEN(CODE)) as Code FROM Prod
) C ON P.Keywords LIKE '%' + C.Code + '%'
AND SUBSTRING(P.Code, 3, LEN(P.Code)) <> C.Code
The above statement joins a unique list of SKU codes (with the letter prefix removed) with every matching record via the join on the Keyword column. Note: This will result in duplicate product records being returned. Additionally the result-set is filtered so as to only return matching records where the SKU Code of the original Product record does not match a SKU code contained in the keywords column.
The distinct then returns only a unique list of Product Id's that have a erroneous SKU code in the Keyword column (they have may have multiples).
Stuff() seems better suited here.... I would do this:
SELECT *
FROM Prod WHERE
Keywords LIKE '%' + STUFF(SKU,1,3,'') + '%'
This will work for both AA 12345 and UN 98767865 -- it replace the first 3 characters with blank.

Create a select statement that turn one column into Mutliple columns using Char Index or something similar

1) Question 1 : Splitting after every 6th digit, basically I need to split my columns after every 5th digit so that 123456 creates to columns , ones with 12345 and a second with 6, I have tried using the code below with no result. there are no spaces or symbols , just digits.
substring(COA.UserCode2,5,charindex('',COA.UserCode2)) as Account,
substring(COA.UserCode2,6,charindex('',COA.UserCode2)) as Project
2) Question 2: Splitting after every * , I can get the first one below to work (Fund) but my cost center and Source don't work basically if I have a string like 1234*34*500, I need the column for fund to have 1234 ( This I got already) , my Cost center to say 34 and my source to say 500
substring(COA.UserCode3, 1,charindex('*',COA.UserCode3)) as Fund,
substring(COA.UserCode3, 3,charindex('*',COA.UserCode3)+1) as CostCenter,
substring(COA.UserCode3, 1,charindex('*',COA.UserCode3)) as Source
Not knowing what DBMS you use (if it has specific SQL extensions etcetera) or how the data looks here is at least some suggestions:
1) If the data is fixed in size (always 6 chars long) you could do this:
SUBSTRING(UserCode2,1,5) as Account, SUBSTRING(UserCode2,6,1) as Project
2) For the second question you could do any of these:
If the data is fixed:
SUBSTRING(UserCode3,1,4) as Fund,
SUBSTRING(UserCode3,6,2) as CostCenter,
SUBSTRING(UserCode3,9,2) as Source
Or if the data is variable and you have to split on the * chars:
SUBSTRING(UserCode3,1,CHARINDEX('*',UserCode3,1)-1) as Fund,
SUBSTRING(UserCode3,CHARINDEX('*',UserCode3,1)+1,CHARINDEX('*',UserCode3,CHARINDEX('*',UserCode3,1)+1) - CHARINDEX('*',UserCode3,1)-1) as CostCenter,
RIGHT(UserCode3,3) as Source
Doing this many CHARINDEX and SUBSTRING functions would probably be bad for performance, but without knowing more about the data it's a bit difficult making informed suggestions.

Splitting text in SQL Server stored procedure

I'm working with a database, where one of the fields I extract is something like:
1-117 3-134 3-133
Each of these number sets represents a different set of data in another table. Taking 1-117 as an example, 1 = equipment ID, and 117 = equipment settings.
I have another table from which I need to extract data based on the previous field. It has two columns that split equipment ID and settings. Essentially, I need a way to go from the queried column 1-117 and run a query to extract data from another table where 1 and 117 are two separate corresponding columns.
So, is there anyway to split this number to run this query?
Also, how would I split those three numbers (1-117 3-134 3-133) into three different query sets?
The tricky part here is that this column can have any number of sets here (such as 1-117 3-133 or 1-117 3-134 3-133 2-131).
I'm creating these queries in a stored procedure as part of a larger document to display the extracted data.
Thanks for any help.
Since you didn't provide the DB vendor, here's two posts that answer this question for SQL Server and Oracle respectively...
T-SQL: Opposite to string concatenation - how to split string into multiple records
Splitting comma separated string in a PL/SQL stored proc
And if you're using some other DBMS, go search for "splitting text ". I can almost guarantee you're not the first one to ask, and there's answers for every DBMS flavor out there.
As you said the format is constant though, you could also do something simpler using a SUBSTRING function.
EDIT in response to OP comment...
Since you're using SQL Server, and you said that these values are always in a consistent format, you can do something as simple as using SUBSTRING to get each part of the value and assign them to T-SQL variables, where you can then use them to do whatever you want, like using them in the predicate of a query.
Assuming that what you said is true about the format always being #-### (exactly 1 digit, a dash, and 3 digits) this is fairly easy.
WITH EquipmentSettings AS (
SELECT
S.*,
Convert(int, Substring(S.AwfulMultivalue, V.Value * 6 - 5, 1) EquipmentID,
Convert(int, Substring(S.AwfulMultivalue, V.Value * 6 - 3, 3) Settings
FROM
SourceTable S
INNER JOIN master.dbo.spt_values V
ON V.Value BETWEEN 1 AND Len(S.AwfulMultivalue) / 6
WHERE
V.type = 'P'
)
SELECT
E.Whatever,
D.Whatever
FROM
EquipmentSettings E
INNER JOIN DestinationTable D
ON E.EquipmentID = D.EquipmentID
AND E.Settings = D.Settings
In SQL Server 2005+ this query will support 1365 values in the string.
If the length of the digits can vary, then it's a little harder. Let me know.
Incase if the sets does not increase by more than 4 then you can use Parsename to retrieve the result
Declare #Num varchar(20)
Set #Num='1-117 3-134 3-133'
select parsename(replace (#Num,' ','.'),3)
Result :- 1-117
Now again use parsename on the same resultset
Select parsename(replace(parsename(replace (#Num,' ','.'),3),'-','.'),1)
Result :- 117
If the there are more than 4 values then use split functions