SQL: checking if row contains contents of another cell - sql

I'm having difficulty with a SQL query.
I have two tables:
Table 1
ID/First Name
1 Ben
2 Barry
3 Birl
Table 2
ID/Full name
1 Ben Rurth
2 Barry Bird
3 Burney Saf
I want to run a check between the two tables where if the contents of the First Name in Table 1 is not in the Full name in table 2 the result will be returned, e.g. returning id 3, Birl, in the above example.
I have been trying queries like:
SELECT First_Name
from Table_1
WHERE NOT EXIST (SELECT Full_name from Table_2)
with no luck so far.

You can make use of LIKE clause combined with concatenation.
SELECT t1.First_Name,t2.Full_Name
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.Full_Name NOT LIKE '%' || t1.First_Name || '%'
Or
SELECT t1.First_Name,t2.Full_Name
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID
WHERE t2.Full_Name NOT LIKE CONCAT('%', t1.First_Name, '%')
This is, understanding that both tables shares the ID column.

Related

SQL multiple join from one row with string

i have two table like this:
table1
id(int) | desc(TEXT)
--------------------
0 | "desc1"
1 | "desc2"
table2
id(int) | table1_id(TEXT)
------------------------
0 | "0"
1 | "0;1"
i want to select data into table2 and replace table1_id by the desc field in table1, when i have string with ';' separator it means i have multiple selections.
im able to do it for single selection like this
SELECT table1.desc
FROM table2 LEFT JOIN table1 ON table1.id = CAST(table2.table1_id as integer);
Output wanted with a SELECT on table2 where id = 1:
"desc"
------
"desc1, desc2"
Im using Postgresql10, python3.5 and sqlalchemy
I know how to do it by extracting data and processing it with python then query again but im looking for a way to do it with one SQL query.
PS: I cant modify the table2.
You can convert the CSV value into an array, then join on that:
select string_agg(t1.descr, ',') as descr
from table2 t2
join table1 t1 on t1.id = any (string_to_array(t2.table1_id, ';')::int[])
where t2.id = 1
That is really an abominable data design.
Consequently you will have to write a complicated query to get your desired result:
SELECT string_agg(table1."desc", ', ')
FROM table2
CROSS JOIN LATERAL regexp_split_to_table(table2.table1_id, ';') x(d)
JOIN table1 ON x.d::integer = table1.id
WHERE table2.id = 1;
string_agg
--------------
desc1, desc2
(1 row)

Compare each row of a table to another table in SQL Server 2008

Here is what I have.
I have two tables, I need to find the value in table 1 that does exist in table 2.
Table 1
----------
John-1
John-2
John-3
John-4
Nancy-1
Nancy-2
Nancy-33
Nancy-4
and
Table 2
--------
Nancy-33
I need to find out if Nancy-33 exists in Table2 then skip all the other values of nancy and display only all the values of JOHN
Thanks
George
If you just want to match on the name portion and then override where there is exact match you can do it with some ugly string splitting:
-- t-sql
SELECT a.name
FROM table1 a
INNER JOIN (
SELECT t1.name
FROM table1 t1
JOIN table2 t2 ON t1.name = t2.name
) b ON a.name = b.name
OR SUBSTRING(a.name, 1, CHARINDEX('-', a.name)) <> SUBSTRING(b.name, 1, CHARINDEX('-', b.name))

sql simple 3 table join using same table?

I have two tables:
Table 1
id, name1
Table 2
id, name2a, name2b
Table 2's column names name2a, and name2b are references to table 1's id. I need to create a query that pulls both the names out of table 1 based on the id's used in Table 2.
Therefore, if Table one contained:
1 Peter
2 Paul
And Table 2 contained:
1 1 2
2 2 2
Then a select statement should give me:
Peter Paul
Paul Paul
I've gone around the bend trying to build this SQL and the best I came up with was:
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1, table2
WHERE table1.id = table2.name2a
Which only gives me the name2a column correctly.
Any help appreciated! I guess I need to do a join, but I'm really struggling...
Start with your 2nd table and join TWICE to table 1 (different aliases respectively), then get the name field from each aliased Table1 entry.
select
T2.ID,
TJ1.Name1 as FirstName,
TJ2.Name1 as SecondName
from
Table2 t2
join Table1 TJ1
on t2.Name2a = TJ1.ID
join Table1 TJ2
on t2.Name2b = TJ2.ID
select foo.*, t1.x, t2.y
join t1 on t1.id = foo.a
join t1 as t2 on t2.id = foo.b
If there's a chance that col a or col b is null, use a left join.
Have you tried using an INNER JOIN?
SELECT table1.name AS 'name', table1.name AS 'Other name'
FROM table1 INNER JOIN table2 ON table1.id = table2.name2a;
Sorry if I'm no help, not that great at SQL myself hehe.
Your problem is that you need to reference table1 twice: once for the plain table1.name and again to look up what table2 is pointing at. You can join one table in multiple times if you give them aliases:
SELECT t1.name1, o.name1
FROM table1 t1
JOIN table2 t2 ON t1.id = t2.name2a
JOIN table1 o ON t2.name2b = o.id -- And JOIN back to table1 to get the name1

mysql - union tables by unique field

I have two tables with the same structure:
id name
1 Merry
2 Mike
and
id name
1 Mike
2 Alis
I need to union second table to first with keeping unique names, so that result is:
id name
1 Merry
2 Mike
3 Alis
Is it possible to do this with MySQL query, without using php script?
This is not a join (set multiplication), this is a union (set addition).
SELECT #r := #r + 1 AS id, name
FROM (
SELECT #r := 0
) vars,
(
SELECT name
FROM table1
UNION
SELECT name
FROM table2
) q
This will select all names from table1 and combine those with all the names from table2 which are not in table1.
(
select *
from table1
)
union
(
select *
from table2 t2
left join table1 t1 on t2.name = t1.name
where t1.id is null
)
Use:
SELECT a.id,
a.name
FROM TABLE_A a
UNION
SELECT b.id,
b.name
FROM TABLE_B b
UNION will remove duplicates.
As commented, it all depends on what your 'id' means, cause in the example, it means nothing.
SELECT DISTINCT(name) FROM t1 JOIN t2 ON something
if you only want the names
SELECT SUM(something), name FROM t1 JOIN t2 ON something GROUP BY name
if you want to do some group by
SELECT DISTINCT(name) FROM t1 JOIN t2 ON t1.id = t2.id
if the id's are the same
SELECT DISTINCT COALESCE(t1.name,t2.name) FROM
mytable t1 LEFT JOIN mytable t2 ON (t1.name=t2.name);
will get you a list of unique names from the 2 tables. If you want them to get new ids (like Alis does in your desired results), that's something else and requires the answers to a couple of questions:
do any of the names need to maintain their previous id. And if they do, which table's id should be preferred?
why do you have 2 tables with the same structure? ie what are you trying to accomplish when you generate the unique name list?

Query three non-bisecting sets of data

I am retrieving three different sets of data (or what should be "unique" rows). In total, I expect 3 different unique sets of rows because I have to complete different operations on each set of data. I am, however, retrieving more rows than there are in total in the table, meaning that I must be retrieving duplicate rows somewhere. Here is an example of my three sets of queries:
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME = t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME <> t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID <> t1.ID
AND t2.NAME = t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
As you can see, I am selecting (in order of queries)
Set of data where the id AND name match
Set of data where the id matches but the name does NOT
Set of data where the id does not match but name DOES
I am retrieving MORE rows than exist in T1 when adding up the number of results returned from all three queries which I don't think is logically possible, plus this means I must be duplicating rows (if it is logically possible) somewhere which prevents me from executing different commands against each set (since a row would have another command executed on it).
Can someone find where I'm going wrong here?
Consider if Name is not unique. If you have the following data:
Table 1 Table 2
ID Name Address ID Name Address
0 Jim Smith 1111 A St 0 Jim Smith 2222 A St
1 Jim Smith 2222 B St 1 Jim Smith 3333 C St
Then Query 1 gives you:
0 Jim Smith 1111 A St
1 Jim Smith 2222 B St
Because rows 1 & 2 in Table 1 match rows 1 & 2, respectively in Table 2.
Query 2 gives you nothing.
Query 3 gives you
0 Jim Smith 1111 A St
1 Jim Smith 2222 B St
Because row 1 in Table 1 matches row 2 in Table 2 and row 2 in Table 1 matches row 1 in Table 2. Thus you get 4 rows out of Table 1 when there are only 2 rows in it.
Are you sure that NAME and ID are unique in both tables?
If not, you could have a situation, for example, where table 1 has this:
NAME: Fred
ID: 1
and table2 has this:
NAME: Fred
ID: 1
NAME: Fred
ID: 2
In this case, the record in table1 will be returned by two of your queries: ID and NAME both match, and NAME matches but ID doesn't.
You might be able to narrow down the problem by intersecting each combination of two queries to find out what the duplicates are, e.g.:
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME = t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
INTERSECT
SELECT DISTINCT t1.*
FROM table1 t1
INNER JOIN table2 t2
ON t2.ID = t1.ID
AND t2.NAME <> t1.NAME
AND t2.ADDRESS <> t1.ADDRESS
Assuming that T2.ID has a unique constraint, it is still quite logically possible for this scenario to occur.If for every record in T1, there are two corresponding records in T2:
Same name, same id, different address
Same name, different id, different address
Then the same record for T1 can come up in the first and third query for example.
It is also possible to simultaneously get the same row in the second and third query.
If T2.ID is not guaranteed to be unique, then you could get the same row from T1 in all three queries.
I think the last query could be the one fetching extra set of rows.
i.e. It is relying on Name matching in both tables (and not on ID)
To find the offending data (and help find your logic hole) I would recommend:
(caution pseudo-code)
Limit the results to just SELECT id FROM ....
UNION the result sets
COUNT(id)
GROUP BY id
HAVING count(id) > 1
This will show the records that match more than one sub-query.