Join on phone numbers in different formats - sql

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)

Related

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

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%'

ORACLE Join tables on a single field and account for minor difference (specific example provided)

I am trying to join two tables on a field (FILE_NAME); however, there are a couple records in just one of the table, in which a timestamp is appended to the end of the file name and before the file extension. I'm not sure how to account for these. I found an Oracle function,
REGEXP SUBSTR (https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions131.htm), that seems like it may give me what I need, but I have to admit that this is extremely advanced to me and am not sure how to apply it.
My sample tables are:
FILE_INFO Table:
FILE_NAME | FILE_ID
REGIONS_ACCOUNTED.xlsx | 21
TSM_INSAT.xml | 14
FILE_PARAMETERS Table:
FILE_NAME
TSM_INSAT.xml
REGIONS_ACCOUNTED-08112017.xlsx
From what I can tell, it seems that the timestamps are always prefixed with a dash (-) so I originally thought to approach it by finding the index of a dash then use substr to concat the before and afters of the timestamp but can't figure out how to do that in a query or how to account for date ranges (e.g.:
REGIONS_ACCOUNTED-07102017-07142017.xlsx
At this point, I just have a basic Join:
SELECT a.file_name, b.file_location
FROM reports.file_info a
LEFT OUTER JOIN reports.file_parameters b on (a.file_name = b.file_name);
The SQL above of course excludes those reports with dates/date ranges in the filename. It would be better to use a file_id, I'm sure; however, there is no file_id in the file_parameters.
Any guidance would be greatly appreciated!
You seem to be looking for match of filenames from FILE_INFO in FILE_PARAMETERS.
SELECT a.file_name,
b.file_location
FROM reports.file_info a
LEFT OUTER JOIN reports.file_parameters b
ON b.file_name LIKE CONCAT('%', SUBSTR(a.file_name, 1, INSTR(a.file_name,'.',-1)-1), '%', SUBSTR(a.file_name, INSTR(a.file_name,'.',-1), LENGTH(a.file_name)), '%');
#Hepc provided the correct answer (in the comments). The modified version to account for date ranges is:
REGEXP_REPLACE(a.file_name,'\-[\d\w\-\_]+.,'.')

SQL - Left Join - On part of string only

I'm trying to make a Left Join, should be simple enough, I have 2 problems;
The values are in Binary
I need to Join the left 3 characters in one string to the right 3 characters of the other (after they are changed from binary)
Join, Left 3 characters of this one
convert(VARCHAR(max),(file_key7), 102)
in db [RF_Sydney].[dbo].[std_file]
with the Right 3 characters of this one
convert(VARCHAR(max),(code_key), 11)
in db [RF_Sydney].[dbo].[std_code]
In SQL Server, you can join on any condition that can be satisfied; in other words, you can do this:
SELECT *
FROM dbo.std_file f LEFT JOIN std_code c
ON LEFT(convert(VARCHAR(max),(f.file_key7), 102), 3)
= RIGHT(convert(VARCHAR(max),(c.code_key), 11),3)
Performance will suck (unless you use persisted computed columns and define an index).
The best way to do this is to use a computed column in each of those tables. This will allow you to simplify your join code, and even allow you to define an index on the column to improve performance if you need it. As for getting the left and right value, there are LEFT() and RIGHT() functions you can use:
LEFT(convert(VARCHAR(max),(file_key7), 102), 3)
and
RIGHT(convert(VARCHAR(max),(code_key), 11), 3)
For the join expression and query itself, we don't have enough information yet to know exactly how you want these to fit together.
Do you know the length of file_key7 or code_key? Joining LEFT(str,len) = RIGHT(str,len) should work but possible take a big performance hit. Maybe you should create field/column and stick your partial keys in it already converted in the right character format

Compare column between two tables (greater and equal to)

I have two table, and i want to compare the two column from those two table. The column reflow in table f_product must greater and equal to column lreflow in table f_line. The coding that I used is
SELECT f_product.oiv,f_product.product,f_product.passive,f_product.pitch,f_product.reflow,f_line.lreflow,f_product.spi,f_product.scomp,f_product.pallet,f_product.printer,f_line.line
FROM f_product,f_line
WHERE f_product.passive=f_line.passive
AND f_product.pitch=f_line.pitch
AND f_product.spi=f_line.spi
AND f_product.pallet=f_line.pallet
AND f_product.printer=f_line.printer
AND f_product.reflow >= f_line.lreflow
AND oiv='PMLE4720A' .
However, the result display out did not compare out the column data in between f_product.reflow and f_line.lreflow. For example, the result still list out the result of reflow=8 and lreflow=10 where reflow is less than the value of lreflow.
Is that my sql coding have any error?
I'm guessing this is Oracle? Sometimes it gets confused by the ambiguity between real where clauses and an implicit join using a where. I would recast it into ansi sql joins:
SELECT
.....
FROM
f_product a INNER JOIN f_line b ON
(a.passive = b.passive AND
a.pitch =b.pitch AND
a.spi=b.spi AND
a.pallet=b.pallet)
where oiv='PMLE4720A'
and a.reflow >= b.lreflow
Assuming the relationship between product and line is such that it makes sense to jion on these four fields...

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