SQL join statement on 2 tables - sql

i am creating a join between two tables Product_Tree and Product on the two columns Model_Number and Manufacturer to return the matching columns.
Here are the 2 tables:
Table : Product_Tree
Col1,Col2,Model_Number,Col3,Manufacturer,Col4
111111,Pepsi,aaa,111111,aaa,description
222222,Miranda,bbb,222222,bbb,'description
333333,Cola,bbb,333333,bbb,description
Table : Product
Model_Number,Manufacturer
a,a
b,b
c,c
d,d
Here is the query:
SELECT Product_Tree.col0,Product_Tree.col1,Product_Tree.col2,Product_Tree.col3,Product_Tree.Model_Number,Product_Tree.Manufacturer
FROM Product_Tree
JOIN Product ON Product.model_number LIKE ''''%''''Product_Tree.MODEL_NUMBER''''%''''
AND Product.manufacturer LIKE ''''%''Product_Tree.MANUFACTURER''''%'''';
I am getting this error:
ORA-00911: invalid character

You'll need to use a concatenation operator to concatenate your % wildcard to your column product_tree.manufacturer:
SELECT Product_Tree.col0,Product_Tree.col1,Product_Tree.col2,Product_Tree.col3,Product_Tree.Model_Number,Product_Tree.Manufacturer
FROM Product_Tree
JOIN Product ON Product.model_number LIKE '%' || Product_Tree.MODEL_NUMBER || '%'
AND Product.manufacturer LIKE '%' || Product_Tree.MANUFACTURER || '%';
I'm guessing that this query is inside a script and is quoted using single quotes ' which is why you have single quotes all over the place in here. If that's the case then your quoted SQL statement would be:
SELECT Product_Tree.col0,Product_Tree.col1,Product_Tree.col2,Product_Tree.col3,Product_Tree.Model_Number,Product_Tree.Manufacturer
FROM Product_Tree
JOIN Product ON Product.model_number LIKE ''%'' || Product_Tree.MODEL_NUMBER || ''%''
AND Product.manufacturer LIKE ''%'' || Product_Tree.MANUFACTURER || ''%'';

Related

How to take multiple rows and make a comma separated list in SQL

I have a query I ran which is
SELECT * FROM rpg.class_primary_abilities AS cpab
INNER JOIN rpg.abilities AS ab ON cpab.ability_id = ab.ability_id
INNER JOIN rpg.classes AS cl ON cpab.class_id = cl.class_id;
It gives me the below output.
What I would like to know is how can I change this query in order to display everything except the first class_id column in a comma separated list. Essentially I would like to get an output of class_idand value,value,value,value,value,value,value,value as my two columns in the output.
I am a college student just learning SQL and have not been exposed to any possible solutions to this problem in class. Any help is appreciated.
Most databases support a function such as string_agg() or listagg() that does what you want:
SELECT cl.class_id,
STRING_AGG(ability_id, ',') as ability_ids,
. . .
FROM rpg.class_primary_abilities cpab JOIN
rpg.abilities ab
ON cpab.ability_id = ab.ability_id JOIN
rpg.classes cl
ON cpab.class_id = cl.class_id
GROUP BY cl.class_id
Please tag your database for more info.
This is one way for Oracle where Ihave used a concatenate sign which is || to concatenate(put two strings together in one) and between them I have also concatenated a comma ,. You can also see that I have used double quotes for the column named desc. I did it because it is not a good practice to call your columns with keywords and word desc is used for example when you order by some column(at the end of the query) you can order by that column ascending then you use asc or descending when you can use desc. Also in both examples I used keyword as to give a name to this concatenated column.
SELECT class_id, cpab.ability_id || ',' ||
ab.ability_id || ',' ||
ab.name || ',' ||
class_id || ',' ||
cpab.name || ',' ||
hit_die || ',' ||
"desc" || ',' ||
isPlayable as values
FROM rpg.class_primary_abilities AS cpab
INNER JOIN rpg.abilities AS ab ON cpab.ability_id = ab.ability_id
INNER JOIN rpg.classes AS cl ON cpab.class_id = cl.class_id;
This is another for MYSQL where I have used concat to concatenate column values and I have used different single quotes for desc column.:
SELECT class_id, concat(cpab.ability_id, ',' ,
ab.ability_id, ',' ,
ab.name, ',' ,
class_id, ',' ,
cpab.name, ',' ,
hit_die, ',' ,
`desc`, ',' ,
isPlayable) as values
FROM rpg.class_primary_abilities AS cpab
INNER JOIN rpg.abilities AS ab ON cpab.ability_id = ab.ability_id
INNER JOIN rpg.classes AS cl ON cpab.class_id = cl.class_id;
In both examples you have columns with same name from different tables and theer you will have to use aliases when calling them in your select clause like I have did in my example: cpab.ability_id and ab.ability_id but please note that I do not know if they are from cpab and ab tables.

SQL query to find matches

I have written a query to provide matches with the same DB and it's giving me expected results except that I don't get few part of it. Below is the query :
select f.name, f.id, f.industry, d.name, d.id, d.industry
from product_table f, product_table d
where (f.name like '%' || d.name || '%') and
(f.industrylike '%' || d.industry|| '%') and
I know by providing this it's actually looking for matches between the 2 columns :
(..... like '%' || ..... || '%')
But what does each part of it do exactly and what does it mean?
This query is executing a self-join (here, a cross self-join) in which we query two instances of the same table for some purpose. In this case it looks like some form of data quality exercise, where we suspect we might have almost duplicate records. That is, we think we have records for the same combination of (product name and industry). The use of wild cards will identify records where the value of one column is wholly embedded in another column: for instance '%STACK%' matches 'META STACKOVERFLOW'.
The posted version has a potential flaw, in that if there are two records with an exact match you will get two hits (one for F:D, one for D:F). You can finagle that by adding a filter on id
select f.name, f.id, f.industry,
d.name, d.id, d.industry
from product_table f, product_table d
where (f.name like '%' || d.name || '%')
and (f.industrylike '%' || d.industry|| '%')
and ( ( f.name = d.name
and f.industry = d.industry
and f.id < d.id )
or f.name != d.name
or f.industry != d.industry
)
The double vertical bar (more commonly known as a pipe) is the concatenation operator. It is used for joining strings together. (Many programming languages use + but Oracle reserves that strictly for arithmetic on numbers.)
not so much clear on why we put it before and after only the second column : f.name like '%' || d.name || '%'
In this case, the query is concatenating a wild card. Given this value for f.name = 'XYZ' , we would get matches for '%' || d.name || '%' on:
'1XYZ1'
'11XYZ11'
'11XYZ'
'XYZ1'
'XYZ' <---- matching same record
We don't need to wrap f.name in wildcard operators because the query is a self-join so all the values of name will appear on the left hand side of the filter. When f.name = '1XYZ1' it match for '%' || d.name || '%' on:
'1XYZ1' <---- matching same record
'XYZ1'
'XYZ'
So you're going to get multiple hits already. Embedding both sides of the filter in wildcards will only generate more noisy duplicates.

change the left join query based on predefined filter-clause(condition)

I have a fine grained SQL query
SELECT A.Form_Id,
B.CONTAINER_ID,
A.FORM_DESC,
A.FORM_TITLE,
A.LAYOUT,
A.TOTAL_COLUMNS,
COUNT (*) Over () AS Total_Rows
,ROW_NUMBER () OVER ( ORDER BY CONTAINER_ID ASC ) ROWNM
FROM FORM_DEFINITION A
LEFT JOIN
(SELECT CONTAINER_ID,FORM_ID FROM FORM_CONTAINER_DEFINITION
) B
On A.Form_Id = B.Form_Id
WHERE UPPER(TRIM(A.FORM_ID)) LIKE '%' || UPPER(TRIM('FORM2')) || '%'
Its working fine in SQL Developer but we are using our own framework. It's adding a dynamic filter-clause (where condition) for every query like this
AND UPPER(TRIM(A.FORM_ID)) LIKE '%' || UPPER(TRIM('FORM2')) || '%'
but as I changed it as
WHERE UPPER(TRIM(A.FORM_ID)) LIKE '%' || UPPER(TRIM('FORM2')) || '%'
I should not change the filter clause. Could you please suggest how can I modify the left-join query to use the pre defined filter-clause.

Searching for list of tables from tab when only partial names of the tables are present

I want to get the list of tables from tab , but I only have partial names of the tables :-
For example:-
SELECT COLUMN_NAME1 FROM TABlE_NAME ;
This returns a list of data : A,B,C,D
The aforementioned data is actually part of a table's name like tableprefix_A_tablesuffix.
I want the list of these tables from TAB or user_tables using partial name available.
This should be ok:
SELECT COLUMN_NAME1 PATTERN, U.TABLE_NAME
FROM TABLE_NAME T, USER_TABLES U
WHERE REGEXP_INSTR(U.TABLE_NAME, '(^|_)' || T.COLUMN_NAME1 || '($|_)') != 0
It retrieves patterns like A_%, %_A_%, %_A.
How about joining the two with the like operator:
SELECT u.table_name
FROM user_tables
JOIN table_name t ON u.table_name like '%' || t.column_name1 || '%'

select record in one table that are not in another with a pattern match

I would like to find all records in the column of one table that are not in a column of another. I can do so with this query:
SELECT
kywd
FROM
from_client
WHERE
kywd NOT IN
(SELECT
kywd
FROM
from_me);
However, I would like to extend this to allow for some pattern matching. At the very least I'd like to see if the from_client kywd appears anywhere in the from_me kywd. So, like, '%kywd%'. I tried ...WHERE '%' || kywd || '%' NOT IN... as a wild guess, and a result set was actually returned, but I suspect this syntax is just gibberish.
How can I make this select statement allow for these wildcards?
not exists is likely to be faster than join
select kywd
from from_client
where not exists (
select 1
from from_me
where position(from_client.kywd, kywd) > 0
)
SELECT from_client.kywd
FROM from_client
LEFT JOIN from_me
ON from_client.kywd LIKE '%' || from_me.kywd || '%'
WHERE from_me.kywd IS NULL
You could try to use the EXCEPT statement. In you scenarion it would be something like
SELECT kywd
FROM from_client
--WHERE <Conditions here>
except
SELECT kywd
FROM from_me
--WHERE <Conditions here>
and returns what exists in from_client that does not exists in from_me.
Try something along these lines.
SELECT
kywd
FROM
from_client
LEFT OUTER JOIN from_me ON
from_client.kywd like from_me.kywd -- replace with whatever appropriate
WHERE
from_me.some_id IS NULL
By "replace with whatever appropriate", I mean:
from_client.kywd LIKE '%' || from_me.kywd || '%'
or
from_me.kywd LIKE '%' || from_client.kywd || '%'
or any other condition which is appropriate there.