How do I use a like in a join with SQL92? - sql

I'm trying to use a like in a join statement. My reason I have one field that is a varchar and another that is also a varchar however, the second field is a comma separated list.
SELECT c.Class, c.SubClass, c.Value, c.Pairs, c.Description, prodt.ProductType, p.Type
FROM pub.table1 c
INNER JOIN pub.Table2 p ON c.SubClass like CONCAT(CONCAT('%',p.Type),'%')
INNER JOIN pub.Table3 prodt ON p.ProdType = prodt.ProductType
WHERE c.Class = 'whatever'
In this case p.Type is the comma separated list and the SubClass is the normal varchar.
I have tried using a few different things already. I would have thought the below worked, but it did not.
INNER JOIN pub.Table2 p ON c.SubClass like '%' + p.Type +'%'
Is there a way to do this or do i have do something different like another select with SQL92? Thank you in advance!

From your explanation, you need to swap the LIKE since p.Type contains the list of values.
p.Type like '%' + c.SubClass + '%'
Your code:
SELECT c.Class, c.SubClass, c.Value, c.Pairs, c.Description, prodt.ProductType, p.Type
FROM pub.table1 c
INNER JOIN pub.Table2 p ON p.Type like '%' || c.SubClass || '% '
INNER JOIN pub.Table3 prodt ON p.ProdType = prodt.ProductType
WHERE c.Class = 'whatever'
Here's a sample test to show this:
select 'matched'
where 'abc' like '%abc,def,ghi,jkl%'
select 'matched'
where 'abc,def,ghi,jkl' like '%abc%'

I am guessing that you want something like this:
ON ',' || p.type || ',' like '%,' || c.subsclass || ',%'
|| has been the string concatenation operator in ISO/ANSI SQL for a long time. To be honest, I don't remember if the adoption of this operator dates back 26 years.

Related

SQL issue with using concatenation inside "like"

I'm trying to use subquery inside "like", sth like this:
select *
from message c
where c.content like (select concat('%', value, '%')
from objects o
where o.orderid = '70008090102484');
and it's returning no results. When I copy paste the output of the select instead of it, it returns one row, so I've tried this:
select *
from message c
where c.content like concat('%', '123', '%'); - no results
select *
from message c
where c.content like '%123%';* - 1 result
I've tried with '%' || '123' || '%' and the same result.
Does anybody have any idea why this is happening?
EDIT: "content" field is of type "bytea" - for varchar it works fine, unfortunately, I'm unable to change this field type
Your first query can be phrased using exists in a structurally-similar way:
SELECT *
FROM message c
WHERE EXISTS (
SELECT 1
FROM objects o
WHERE c.content LIKE CONCAT('%', o.value, '%') AND
o.orderid = '70008090102484'
);

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.

Append Table Name to Field Name with Select *

Sorry if this is a duplicate. I have searched but only find aliasing fields and tables.
I have a query:
SELECT *
FROM MyTable1 ca LEFT OUTER JOIN MyTable2 dcn ON dcn.dstrct_code = ca.dstrct_code
LEFT OUTER JOIN MyTable2 cdn ON cdn.dstrct_code = ca.cost_dstrct_cde
LEFT OUTER JOIN MyTable3 bb ON bb.supplier_code = ca.supplier_code
WHERE ca.dstrct_code = '0001'
AND ca.req_232_type = 'P'
AND ca.requisition_no = '264982 000'
AND ca.alloc_count = '01'
ORDER BY ca.alloc_count ASC
Please dont shoot me down for using * im not done with the query yet. If I execute this query I get a row of data however the tables I am selecting from all have a good number of fields and many are simularly named. So my question is... Is there anyway to select * from and append the table name to the field name so it is more obvious which field belongs to which table?
I don't think there's a way to do that directly but you can do this instead. Run a query like this:
SELECT
(case t.name when 'MyTable1' then 'ca' when 'MyTable2' then 'dcn' when 'MyTable3' then 'cdn' when 'MyTable4' then 'bb' end)
+ '.' + c.name
+ ' AS "' + t.name + '.' + c.name + '",'
FROM sys.tables AS t
INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
WHERE t.name in ('MyTable1', 'MyTable2', 'MyTable3', 'MyTable4')
ORDER BY t.name
Run it, preferably with results to Text (Ctrl+T), and use the results instead of the * in your original query. You have to manually remove the comma from the last line.
If you like the approach, you could streamline the process with some dynamic SQL.