sql join string match - sql

lets say i have 2 tables
ID Product
----------------
micrsoft sql
cisco
ID Product
----------------
sql
cisco agent
flash
I need to write a query that returns only 'flash' as output becasue it does not have a match on table 1. The words cisco and microsoft have matches on the other table and so needs to be discarded.
This is more of an inner join but using pattern/string match/contains. The strings needs not be an absolute match and can also be a subset . for eg. you have cisco in one table and cisco agent in the other .
/****** Script for SelectTopNRows command from SSMS ******/
SELECT
[Product]
FROM t1 INNER JOIN t2
ON t1.Product= t2.Product
order BY Product
will only satisy those products whose value exactly match . But i would need to query even partial matches

You can use like for this purpose:
SELECT t2.[Product]
FROM t2 LEFT JOIN
t1
ON t1.Product LIKE '%' + t2.Product + '%' OR
t2.Product LIKE '%' + t1.Product + '%'
WHERE t1.Product IS NULL
ORDER BY t2.Product;
Performance will not be good, so I hope you don't have too much data.

Try this:
select Id, Product
from table2 t2
where ID Not IN ( Select IDFrom table1 )

Related

SQL Matching a string that contains a string

I have two tables in database.
Both tables have a business name column but not always going to be the same.
For example tbl 1 has a business name of 'Aone Dental Practices Limited TA Jaws Dental' and Tbl 2 has a business name of 'Jaws Dental'. I want to be able to join these together as Jaws Dental is visible in both.
I can't seem to get the Like clause working for this.
tried
Tbl1_BusinesName Like '%' + Tbl2_BusinesName + '%'
This query should work :
SELECT *
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.BusinesName LIKE '%'+TS.BusinesName+'%'
Using EXISTS you can get the expected result:
SELECT *
FROM dbo.TableName1 AS Tbl1
WHERE EXISTS (SELECT 1
FROM dbo.TableName2 AS Tbl2
WHERE Tbl1.BusinesName LIKE '%' + Tbl2.BusinesName + '%');

SQL Select statement (from 2 different tables)

Heyy I'm new to sql and I'd just like to know if there's a way to retrieve select statements with conditions from other tables.
I want to select all name values that have a number that identifies that they have committed a crime. I only want to select a name once.
"SELECT distinct * FROM Table1 WHERE number LIKE table2.number "
Are you looking for IN?
SELECT t1.*
FROM Table1 t1
WHERE t1.number IN (SELECT t2.number FROM table2 t2 t2.number);
Under most circumstances, the rows in a table should be unique. So, you don't need SELECT DISTINCT. The DISTINCT can add a considerable amount of overhead to such a query.
You can able to use INNER JOIN like below,
select tbl1.Name from tableOne tbl1
inner join tableTwo tbl2 ON tbl1.commonKey = tbl2.commonKey
where tbl1.columnName = 'any value'

How to use a subquery result for another sql select?

I want to use the result of a sql query and send another query based on the result.
Exmaple (of course real live query is more complex):
table1: name, age
table2: name, age, field1, fieldN
First query:
select name, age from table1 where age > 18.
Now I'd like to find all entries from table2 that match the multiple resulting fields of the first query.
Important note: I want to retrieve the full rows of table2 where the match is.
But how?
If you want to automatically join based on matching column names, then you can use a NATURAL JOIN:
WITH query1 AS (
SELECT age, name FROM table1 WHERE age > 18
)
SELECT age, name, t2.field1, t2.fieldN
FROM table2 t2 NATURAL JOIN query1;
Now, while NATURAL JOIN is generally not recommended, as it is really weak because your queries using it can easily brake due to schema changes, it may be OK for hand ad-hoc queries, or for queries, like the above, where you can make the columns used explicit. In either case, I advise against it and use the common join style:
WITH query1 AS (
SELECT age, name FROM table1 WHERE age > 18
)
SELECT t2.age, t2.name, t2.field1, t2.fieldN
FROM table2 t2 JOIN query1 q1 ON t2.age = q1.age AND t2.name = t1.name;
Now I'd like to:
find
all entries from table2
that match the multiple resulting fields
of the first query
SELECT * -- find
FROM table2 t2 -- from t2
WHERE EXISTS (
SELECT * FROM table1 t1
WHERE t1.name = t2.name -- that match
AND t1.age = t2.age -- Huh? "multiple matching fields" ?
AND t1.age > 18 -- with the same condition
);
Actually this is what I was looking for, but thanks for any help:
select * from table2 where (name, age) IN (
select name, age from table1 where age > 18
)
Query build based on MS sql server
select t1.*
from table1 as t1
join table2 as t2 on t1.name=t2.name and t1.age=t2.age
where t2.age > 18

Combine LIKE and IN using only WHERE clause

I know this question has been asked, but I have a slightly different flavour of it. I have a use case where the only thing I have control over is the WHERE clause of the query, and I have 2 tables.
Using simple example:
Table1 contains 1 column named "FULLNAME" with hundreds of values
Table2 contains 1 column named "PATTERN" with some matching text
so, What I need to do is select all values from Table 1 which match the values in table 2.
Here's a simple example:
Table1 (FULLNAME)
ANTARCTICA
ANGOLA
AUSTRALIA
AFRICA
INDIA
INDONESIA
Table2 (PATTERN)
AN
IN
Effectively what I need is the entries in Table1 which contain the values from Table2 (result would be ANTARCTICA, ANGOLA, INDIA, INDONESIA)
In other words, what I need is something like:
Select * from Table1 where FULLNAME IN LIKE (Select '%' || Pattern || '%' from
Table2)
The tricky thing here is I only have control over the where clause, I can't control the Select clause at all or add joins since I'm using a product which only allows control over the where clause. I can't use stored procedures either.
Is this possible?
I'm using Oracle as the backend DB
Thanks
One possible approach is to use EXISTS in combination with LIKE in the subquery:
select * from table1 t1
where exists (select null
from table2 t2
where t1.fullname like '%' || t2.pattern || '%');
I believe that you can do this with a simple JOIN:
SELECT DISTINCT
fullname
FROM
Table1 T1
INNER JOIN Table2 T2 ON T1.fullname LIKE '%' || T2.pattern || '%'
The DISTINCT is there for those cases where you might have a match to multiple rows in Table2.
If the patterns are always two characters and only have to match the start of the full name, like the examples you showed, you could do:
Select * from Table1 where substr(FULLNAME, 1, 2) IN (Select Pattern from Table2)
Which prevents any index on Table1 being used, and your real case may need to be more flexible...
Or probably even less efficiently, similar to TomH's approach, but with the join inside a subquery:
Select * from Table1 where FULLNAME IN (
Select t1.FULLNAME from Table1 t1
Join Table2 t2 on t1.FULLNAME like '%'||t2.Pattern||'%')
Right, this involved a bit of trickery. Conceptually what I've done is turned the column from the PATTERN into a single cell, and use that with REGEX_LIKE
So the values "AN and IN" becomes one single value '(AN|IN)' - I just feed this to the regexp_like
SELECT FULLNAME from table1 where
regexp_like(FULLNAME,(SELECT '(' || SUBSTR (SYS_CONNECT_BY_PATH (FULLNAME , '|'), 2) || ')' Table2
FROM (SELECT FULLNAME , ROW_NUMBER () OVER (ORDER BY FULLNAME) rn,
COUNT (*) OVER () cnt
FROM Table2)
WHERE rn = cnt START WITH rn = 1 CONNECT BY rn = PRIOR rn + 1))
The subquery in the regexp_like turns the column into a single cell containing the regular expression string.
I do realise this is probably a performance killer though, but thankfully I'm not that fussed about performance at this point

SQL Select Query - "Pairing" Records Together

Here's my data:
Table1...
id
field1
field2
...
Table2...
id
table1_original_id
table1_new_id
Table1 holds records that cannot themselves be updated though I built a mechanism for my users to be able to "update" them... they select a record, make changes, and those changes are actually submitted as a new record. For conversation's sake let's assume there are currently 10 records in Table1 with IDs 1 through 10. User submits an update to ID 3. ID 3 remains as it was and a new record, ID 11, is added to Table1. Along with this new record, Table2 gets a new record, with ID = 1, t1_original_id = 3 and t1_new_id = 11.
What would be by SQL select to retrieve the "pairs" of records from Table1... in this case the query would provide me with... IDs 3 and 11.
scratching head
I don't think it matters much by DB platform is Postgres 8.4 and I'm retrieving the data via PHP to be processed in jqGrid. Bonus points if you can point me in the direction of displaying each pair of records in a separate jqGrid!
Thanks for your time and effort.
=== EDIT ===
The following is a sample of what I need returned from the query based on the scenario above:
id field1 field2
3 blah stuff
11 more things
Once I have these pairs back I can process them further, as necessary, on the PHP side.
Standard SQL solution
To get two separate rows (as later specified in the Q update) use a UNION query:
SELECT 'old' AS version, t1.id, t1.field1, t1.field2
FROM table1 t1
JOIN table2 t2 ON t2.table1_original_id = t1.id
WHERE t2.id = $some_t2_id -- your t2.id here!
UNION ALL
SELECT 'new' as version, t1.id, t1.field1, t1.field2
FROM table1 t1
JOIN table2 t2 ON t2.table1_new_id = t1.id
WHERE t2.id = $some_t2_id; -- your t2.id here!
Note: this is one query.
Returns as requested, plus a column version to distinguish the rows reliably:
version | id | field1 | field2
--------+----+--------+--------
old | 3 | blah | stuff
new | 11 | more | things
Faster Postgres-specific solution
A more sophisticated, but shorter and faster solution:
SELECT version, id, field1, field2
FROM (
SELECT unnest(ARRAY['old', 'new']) AS version
,unnest(ARRAY[table1_original_id, table1_new_id]) AS id
FROM table2 t2 WHERE t2.id = $some_t2_id -- your t2.id here!
) t2
JOIN table1 USING (id);
Same result.
-> SQLfiddle demo for both.
You'll need to JOIN to Table1 twice, something like:
SELECT orig.id AS Orig_ID
, orig.value AS Orig_Value
, n.id AS New_ID
, n.value AS New_Value
FROM Table2 a
JOIN Table1 AS orig
ON a.table1_original_id = orig.id
JOIN Table1 AS n
ON a.table1_new_id = n.id
Demo: SQL Fiddle
Update:
To get them paired as you want without manually choosing a set you'll need something like this:
SELECT sub.id,sub.value
FROM (SELECT a.id as Update_ID,o.id,o.value, '1' AS sort
FROM Table2 a
JOIN Table1 AS o
ON a.table1_original_id = o.id
UNION
SELECT a.id as Update_ID, n.id,n.value, '2' AS sort
FROM Table2 a
JOIN Table1 AS n
ON a.table1_new_id = n.id
) AS sub
ORDER BY Update_ID,sort
Demo: Sql Fiddle
Notes: Change UNION to UNION + ALL, can't post those words next to each other due to firewall limitation.
The hard-coded '1' and '2' are so that original always appear before new.