SQL join question - sql

I have a table table_a with a column containing data as follows:
.aaa01932
.asd02343
.lkj03342
So it always starts with a period followed by 3 letters, followed by 2 number (01, 02 etc) followed by some extra numbers.
I have another table table_b with data as follows:
aaa01
asd02
lkj03
So it maps to the data in table_a but with the period and the extra numbers at the end omitted.
How do I select from table_a joining on table_b where the data in the shown columns are "equal". By equal I mean that table_a.the_column like '%table_b.the_column%'. So something like:
Select * from table_a
join table_b on (table_a.the_column like '%table_b.the_column%');
Except I don't know how to format that like clause to accept a column inside. Maybe I need to concatenate it in somehow?

The syntax for the LIKE would be:
table_a.the_column like '%' || table_b.the_column || '%'
An alternative would be SUBSTR:
table_b.the_column = substr(table_a.the_column,2,5)
As some comments have said, the SUBSTR is a better method for 2 reasons:
It can be indexed:
create index on table_a (substr(the_column,2,5));
It is more accurate: you want to match only in that position, not anywhere in the column

Try this:
Select * from table_a
join table_b on (table_a.the_column like '%' || table_b.the_column || '%');

join table_b on substr(table_a.column,1) = table_b.column

Related

Required to create an empty table by joining multiple tables in Oracle DB

I got an error while creating an empty table by joining two tables.
I have two tables tab1 & tab2 and there are many common columns names in both tables.
I tried this:
create table tab3 as
select * from tab1 a, tab2 b where a.id = b.id and 1=2;
This gave ORA-00957: duplicate column name. As I mentioned above there are many common columns name between these two tables. If I prepare a create table statement by writing around 500 column names one by one then it will consume lots of time. Please help me out here.
The simple answer is, don't use *. Or is that the whole point, to avoid writing five lines of column names?
One way to avoid these conflicts, but that assumes that you are joining on all columns with the same name in both tables and on no other columns, is to do something like
create table new_table as
select *
from table_a natural join table_b
where null is not null
;
(As you can guess, as an aside, I prefer null is not null to 1 = 2; the parser seems to prefer it too, as it will rewrite 1 = 2 as null is not null anyway.)
Will you need to control the order of the columns in the new table? If you do, you will need to write them out completely in the select clause, regardless of which join syntax you choose to use.
That's an interesting question.
The only idea I have to offer it to let another query to compose the query you need
select 'select ' || listagg(col_name, ', ') within group(order by 1) || 'from tab1 a,tab2 b where (a.id=b.id) and 1=2'
from (select 'a.' || column_name col_name from user_tab_cols where table_name = 'TAB1'
union all
select 'b.' || column_name from user_tab_cols where table_name = 'TAB2')
Please be aware for subqueries you need to specify table names in the upper case

PostgreSQL: Joining Tables Based on Searched Concatenated Strings

I'm not sure how to write a join clause that takes a value from table 1, then searches a string in table 2 to see if they match. Sound confusing?
Here's the actual example I'm working with.
Table 1
Customer_Id Concat_Phone_Numbers
1 8888888888;1111111111
Table 2
Caller Callee Calldate
1111111111 3333333333 1/1/1900
I want to create a table that looks like this:
Desired Table
Customer_Id Calldate
1 1/1/1900
I'm lost when it comes to writing the join clause so that the entire list in Table 1's second column is searched for a matching phone number/entry.
Thank you in advance for your help! (PS it's my first time asking a question!)
Edit::
Here's where I'm at now
Select
*
from table1
left join table2
on ??????????????????
Yuck! You should fix the data structure. You really need a table with one row per customer and per phone number. You'll understand why if you care about performance.
But, if you are stuck with this data model, you can do a join using string and/or array operations. Here is a method using regular expressions
select . . .
from table1 t1 left join
table2 t2
on t2.caller ~ '^' || replace(t1.phone_numbers, ';', '|') || '$' or
t2.callee ~ '^' || replace(t1.phone_numbers, ';', '|') || '$' ;

"NOT IN" subquery with a leading wildcard

I have two tables:
Table tablefoo contains a column fulldata.
Table tablebar contains a column partialdata.
I want find a list of tablefoo.fulldata that do NOT have partial matches in tablebar.partialdata.
The following provides a list of tablefoo.fulldata with partial matches in tablebar, but I want the negative of this.
select fulldata from tablefoo
where fulldata like any (select '%' || partialdata from tablebar);
This lists every record in partialdata:
select fulldata from tablefoow
where partialdata not in (select '%' || partialdata from tablebar);
Any idea how to get only the results tablefoo.fulldata that do not contain matches to a leading wildcarded tablebar.partialdata?
I found this link: PostgreSQL 'NOT IN' and subquery which seems like it's headed down the right path, but I'm not getting it to work with the wildcard.
Sure, I could write a script to pull this out of psql and do the comparisons, but it would be much nicer to handle this all as part of the query.
SELECT fulldata
FROM tablefoo f
WHERE NOT EXISTS (
SELECT 1
FROM tablebar b
WHERE f.fulldata LIKE ('%' || b.partialdata)
);

Pattern matching on strings from a table in SQL

Just wanted to know if it was possible to do a pattern matching on a set of data from a table.
Like:
select * from Table where Column like any(select Pattern from PatternTable)
Note that the Pattern is always a substring of Column. Hence the use of like. Is it even possible to do this at a database level without the use of stored procedures?
If it helps, my RDBMS is MS SQL-Server
Edit:
Alright, I have a table containing a set of data like
PatternTable
____________
test1
test2
test3
test4
Now, a table Table has the following data:
Table
______
SomeDatatest4SomeData
SomeDataSomeData
Now, can I use a query as mentioned above to find a match: For the above query, this should return SomeDatatest4SomeData
You can do this using exists:
select *
from Table t
where exists (select 1
from PatternTable pt
where t.Column like pt.Pattern
);
SELECT t.*
FROM [Table] t
INNER JOIN PatternTable p ON t.[Column] LIKE '%' + p.Pattern + '%'

Where the value of one column is contained in the value of another column

I'm trying to write a query which compares two tables and finds all entries where one field is contained in another field. For example one field contains a single 5 digit login ID eg 12345. The second field contains one or multiple IDs seperated by commas but with the characters text^ in front eg text^12345 or text^12345,54321,13579,97531
If I try
Select * from table1.login_id a
join table2.login_id b
on b.login_id LIKE '%' + a.login_id + '%'
I am finding is that it is only joining on the last entry in the list. So if a.login_id = 12345 it only brings back where b.login_id = text^12345 or text^54321,12345 but not text^12345,54321
Am I just missing something?
Note: I am using SQL Server 2008, so the query can't use CONCAT.
You need to use CONCAT() to assemble your string:
Select * from table1.login_id a
join table2.login_id b
on b.login_id LIKE CONCAT('%', a.login_id, '%')
Perhaps a where exists is appropriate:
select * from table1 as a where exists (
select b.login_id from table2 as b where a.login_id like concat('%', b.login_id, '%')
);
You are missing something. Your issue is not reproducible.
When I run the following:
DECLARE #Table1 TABLE (login_id varchar(255));
DECLARE #Table2 TABLE (login_id varchar(255));
INSERT INTO #Table1 VALUES ('12345');
INSERT INTO #Table2 VALUES ('text^12345,54321');
Select * from #Table1 a
join #Table2 b
on b.login_id LIKE '%' + a.login_id + '%';
I get:
login_id | login_id
12345 | text^12345,54321
So when you say
it only brings back where b.login_id = text^12345 or text^54321,12345
but not text^12345,54321
You are wrong. It does bring that text back. Find the difference between the query you posted in your question, and the actual query you are using, and you will find what you are missing. Or if there is no difference in the query, then the difference is in the data. The data in your question may not be comparable to your actual data.