SQL query to get rows contains value of another query - sql

I have 2 tables transaction and query. Transaction table have unique tid and the query table has tid_(subtransactionid).
I want to get the list of all subtransactions by using tid.
I tried this
select *
from queries, transactions
where queries.id like 'transactions.tid%' and transactions.uid = 'NfPgWM1igYh2y2hDKrLWLOxyI6u1'

You can join the tables and use the operator LIKE in the ON clause:
select q.*
from queries q inner join transactions t
on q.tid like concat(t.tid, '%')
where t.uid = 'NfPgWM1igYh2y2hDKrLWLOxyI6u1'
If your database does not support the function concat() then you can use either:
on q.tid like t.tid || '%'
or:
on q.tid like t.tid + '%'

Related

SQL Join with partial string match

I have a table 'TableA' like:
ID Group Type
1 AB SomeValue
2 BC SomeValue
Another table 'TableB' like:
Product Subgroup Type
A XX-AB-XX-text SomeValue
B XX-BC-XY-text SomeValue
I am using INNER JOIN between two tables like:
SELECT DISTINCT ID
FROM TableA TA
INNER JOIN TableB TB
ON TA.Type=TB.Type
I want to add another condition for join, which looks for value of 'Group' in 'Subgroup' and only joins if the 'Group' Value matches after 'XX-' and before '-XX'.
In other words, join only if Group 'AB' shows up at the correct place in Subgroup column.
How can I achieve this? I am using MSSQL
Try this:
SELECT (DISTINCT ID)
FROM TableA TA
INNER JOIN TableB TB
ON TA.Type=TB.Type AND TB.SubGroup LIKE '__-' + TA.Group + '%'
You can use LIKE with CONCAT to build the expression, see this fiddle:
https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d7bb4781488e53c31abce0f38d0aaef4
SELECT *
FROM TableA TA
JOIN TableB TB on (
TA.types = TB.types AND
TB.subgroup LIKE concat('XX-', TA.groups, '-XX%')
);
I am dumping all the returned data so you can see it, but you would want to modify that to return only DISTINCT TA.id.
It is possible to build the expression using + instead of CONCAT:
'XX-' + TA.groups + '-XX%'
Also, I would very strongly warn you against using column names that are reserved words. Both GROUP and TYPE are in use by the SQL engine, so to use them you would have to escape them every time, and they might also cause confusion to anybody reading or maintaining your code.

How to search if a row is a substring of another row of the same column in Oracle

I have a table that contains millions of rows for names of customers as a column. I want to find if a part of a name exists within another row in the same column.
E.g. If a row has value 'Roger Federer' and there are other rows with values, 'Roger' and 'Federer', I want the corresponding primary keys of all the three rows.
You can leverage the use of REGEXP_LIKE
SELECT *
FROM customers
WHERE REGEXP_LIKE (cust_name, 'roger|federer','i')
SQL Fiddle Demo
More examples of REGEXP_LIKE usages can be found here
Another option would be the use of OR
SELECT *
FROM customers
WHERE LOWER(cust_name) LIKE LOWER('%roger%')
OR LOWER(cust_name) LIKE LOWER('%federer%')
SQL Fiddle Demo
Edit
With the use of JOIN, the search string is dynamic. If proper indexes are in place, then it would not have much impact.
SELECT DISTINCT
c1.*
FROM
customers c1
JOIN
customers c2
ON ( LOWER(c1.cust_name) LIKE LOWER(c2.cust_name || '%')
AND c1.cust_id != c2.cust_id)
SQL Fiddle Demo
Edit 2
Perhaps something like the below
SELECT DISTINCT
c1.cust_id,
c1.cust_name,
CASE
WHEN
LOWER(c1.cust_name) LIKE LOWER(c2.cust_name || '%')
THEN
'Matched'
ELSE
'Unmatched'
END
ident
FROM
customers c1
JOIN
customers c2
ON ( LOWER(c1.cust_name) LIKE LOWER(c2.cust_name || '%')
AND c1.cust_id != c2.cust_id)
SQL Fiddle Demo
If you want to construct a logic related to rows, union concepts may suit well,
by the way, in string operations we'd better use collations with patterns through upper or lower functions to satisfy case-insensitivity for letters :
select id from customers where lower(name) like '%roger%' union all
select id from customers where lower(name) like '%federer%';
and no need to add already included complete name ( e.g. Roger Federer ).
Edit :
An Alternative method maybe the following :
select distinct id
from (select lower(regexp_substr('&str', '[^[:space:]-]+', 1, 1)) frst,
lower(regexp_substr('&str', '[^[:space:]-]+', 1, 2)) lst,
lower('&str') nm
from customers) c1
cross join customers c2
where c1.frst like '%' || lower(c2.name) || '%'
or c1.lst like '%' || lower(c2.name) || '%'
or c1.nm like '%' || lower(c2.name) || '%';
by adding a search string('&str') to make the query more dynamic as you wish.
( when prompted enter Roger Federer for str substitution variable )
I think you can use join same table twice (self join) to get output with below query,
select a.*, b.*
from tab1 a
, tab1 b
where ( a.fname like b.fname||'%' or a.lname like b.lname||'%')
and a.id <> b.id

query inside like operator

Can I use query inside the like operator.
I used the query below, but it returns error.
select *
from customers
where cust_name like '%'||select name from members||'%'
Something like the following should work :
SELECT
*
FROM
customers c
WHERE 1=1
AND EXISTS
(SELECT 1
FROM members m
WHERE 1=1
AND c.cust_name LIKE '%'||m.name||'%'
)
In PLSQL if you want to run a Query then you need to decalre a variable to hold the result of the query. So you can do it as :
DECLARE
var customers%ROWTYPE;
BEGIN
SELECT c.*
INTO var
FROM customers c
INNER JOIN members m ON c.cust_name LIKE '%' || m.name || '%';
END;
it is sufficient to enclose the subquery in parentheses
like as
cust_name like '%'||(select name from members)||'%'
but this only works when the table "members" has only one record
You should define the name part of members in subselect (works with only 1 row):
select *
from customers
where cust_name like (select '%'||name||'%' from members);
Same can be done with JOIN (works with multiple rows):
select C.*
from customers C
INNER JOIN MEMBERS M ON (C.CUST_NAME LIKE '%'||M.NAME||'%');

Need only one match from a Left Join

Hello thanks for taking the time to read this.
I have a table TBL_INCIDENT containing columns TXT_INC_ID and TXT_SERVICE, I am using a LEFT JOIN to join it to table TBL_ASMS containing TXT_APPLICATION_ID. The issue I am having is the join will have multiple matches and I only want the first one. I saw an example of code using LIMIT 1, but I am unsure syntactically how it is supposed to be used. I also have seen some solutions for duplication using row_number() over partition, but I could not find one that was a select statement, only deletes.
This is my current state:
SELECT COUNT(A.TXT_INC_ID)
FROM(
SELECT A.TXT_INC_ID, B.APPLICATION_ID
FROM TBL_INCIDENT A
LEFT JOIN TBL_ASMS B ON A.TXT_SERVICE LIKE ('%' || B.APPLICATION_ID || '%') LIMIT 1
)
TXT_INC_ID is the primary key in the table it comes from, and I only want one match per record to be returned by the left join. I am using left because I need every record in table A returned, but only once.
Thanks
Maybe use a Max?
SELECT COUNT(A.TXT_INC_ID)
FROM(
SELECT A.TXT_INC_ID, Max(B.APPLICATION_ID)
FROM TBL_INCIDENT A
LEFT JOIN TBL_ASMS B ON A.TXT_SERVICE LIKE ('%' || B.APPLICATION_ID || '%')
group by A.txt_inc_id
)
Your result is logically the same as:
SELECT COUNT(A.TXT_INC_ID)
FROM TBL_INCIDENT A

Joining a derived table based on specific data from the outside query

I am trying to join one record in a table to another using a derived table and am having a bit of trouble figuring out the correct query to do so. What I want to do is have a JOIN of a derived table to a query where the derived table uses where statements depending on data from the outer query that is being joined to. So here is the current code that I am working on:
SELECT a.viewerid, a.id, v.id AS entry, a.jobid, v.sourceid, v.cost, a.applicant
FROM a_views a,
JOIN (
SELECT TOP 1 id, sourceid, cost FROM a_views vt
WHERE vt.viewerid = a.viewerid
AND vt.viewed_at <= a.viewed_at
AND vt.referrer NOT LIKE '%' + vt.hostName + '%'
ORDER BY viewed_at DESC
) v
The derived table is a query of the same table that the outer query uses, and viewerid is a FK to itself across the table where id is a unique auto-incrementing PK. I need to get the latest record in the a_views table where the viewer id's match, the datestamp (viewed_at) is less than the outer datestamp and the referrer column doesn't contain the hostName column.
Sounds like you need APPLY:
SELECT a.viewerid, a.id, v.id AS entry, a.jobid, v.sourceid, v.cost, a.applicant
FROM a_views a
CROSS APPLY (
SELECT TOP 1 id, sourceid, cost FROM a_views vt
WHERE vt.viewerid = a.viewerid
AND vt.viewed_at <= a.viewed_at
AND vt.referrer NOT LIKE '%' + vt.hostName + '%'
ORDER BY viewed_at DESC
) v
Since your query has JOIN I've gone for CROSS APPLY, but you may need OUTER APPLY depending on your exact requirements.