Select from two tables in MySQL - mysql

I have two tables with users and I want to select the users from the first table which do not exist in the second. Can you help me?
When I use the code
Select t1.user_name From t1 Inner Join t2 On t1.user_name != t2.user_name;
I get all the users many times (actually as the number of the users - 1).

Use a LEFT JOIN instead like
Select t1.user_name From t1 left join t2
On t1.user_name = t2.user_name
where t2.user_name is null;

You can use EXISTS like this
SELECT t1.user_name FROM t1 WHERE NOT EXISTS (SELECT 1 FROM t2 WHERE t1.id = t2.id)
This example assumes that you have some sort of ID on the tables that represents the primary key and foreign key.
Not sure how are your tables designed, but having the same info (user_name) in more than one table is considered as duplication of data. To fix this, you should read about Database normalization

Related

INNER JOIN creates duplicate primary key error but it shouldn't

I'm trying to make a new table from the inner join results of three other tables (t1, t2, t3)
INSERT INTO new_table
SELECT
t1.application_id,
t1.text,
t2.names,
t2.title,
t3.org_name, t3.project_start, t3.project_end, t3.keywords
FROM t1
INNER JOIN t2 ON t1.application_id = t2.application_id
INNER JOIN t3 ON t1.application_id = t3.application_id;
but keep getting a ER_DUP_ENTRY: Duplicate entry '9481301' for key 'PRIMARY'error. Each table should have id as a primary key so I'm confused why this is happening - how would one find and delete all the duplicates?
I bet your new_table is defined with an AUTOINCREMENT primary key.
To make your INSERT work correctly you'll need to let MySQL set that value rather than providing it from your SELECT. Something like this may work for you.
INSERT INTO new_table
(text, names, title, org_name, project_start, project_end, keywords)
SELECT
t1.text,
t2.names,
t2.title,
t3.org_name, t3.project_start, t3.project_end, t3.keywords
FROM t1
INNER JOIN t2 ON t1.application_id = t2.application_id
INNER JOIN t3 ON t1.application_id = t3.application_id;
You do this by leaving the id value out of your SELECT, and by enumerating the columns you want to INSERT.
(This is a guess: you didn't show us your table definition.)

How to join where duplicates are needed?

I have a table structure like this
Table1
PersonID, referrer
Table2
Event_A_ID, PersonID, status
Table3
Event_B_ID, PersonID, status
I want to get the event status for everyone from table one with referrer=X by joining all of the event tables like Event_A...K and checking for PersonID. Since people can appear in multiple events we can have cases like this
PersonID=1001, EventA_ID, referrer=X, status
PersonID=1001, EventB_ID, referrer=X, status
PersonID=1001, EventK_ID, referrer=X, status
PersonID=1002, ...
PersonID=1003, ...
But I am not sure how to JOIN all of the event tables since the IDs can be duplicates (and are desired).
I tried to make a separate select and use the in syntax
...
WHERE 1=1
AND PersonID IN (SELECT PersonID from table1 where referrer=X)
But then I realized everything before will be an aggregate of events.
Should I start with the SELECT from Table1? Select the valid IDs first and then select from the events after? If so, how do I JOIN? I feel like ideal looks like union of all the event tables and then select
You can use union all for row wise implementation of data or you can also use inner joins between tables if there is not much table events. This will represent data in column format.
SELECT * FROM tb2 AS t2 INNER JOIN tb3 t3 ON t2.personId = t3.personId INNER JOIN tb1 t1 ON t1.personId = t2.personId WHERE t1.refer='refer1'
There can be many other approach too depending on the number of tables you want to join.
You should also consider to use a better relations among your db tables as your current scenario will lead you to have as many tables as many events you have. This will create slowness in retrieving the data for multiple events.
use union all and then apply join
select a.person_id,a.referrer,b.eventID,b.PersonID,b.status from Table1 a inner join
(
select Event_A_ID as eventID, PersonID, status from Table2
union all
select Event_B_ID as eventID, PersonID, status from Table3
)b on a.personid=b.personid
You can do something like this with left joins:
SELECT t1.PersonID, t1.referrer,
t2.Event_A_ID, t2.status as status_a,
t3.Event_B_ID, t3.status as status_b
.
.
.
FROM table1 t1
LEFT JOIN table2 t2 ON t2.PersonID = t1.PersonID
LEFT JOIN table3 t3 ON t3.PersonID = t1.PersonID
.
.
.
WHERE t1.referrer = 'x'

LEFT JOIN to show NULL rows + WHERE

I have two tables, one which contains unique names (bill_datatypes), and another one which expresses that these names are connected to some subcategories (one name can be connected to more categories as well).
The first table (relevant part):
The second table (relevant part):
I would like to select all the names which are not connected to a specific subcategory yet. This means that the names might be mentioned in the connecting table but connected to a different subcategory.
I have solved the problem with the following subquery:
SELECT T1.name
FROM bill_datatype T1
WHERE NOT EXISTS (
SELECT T2.bill_datatype_id
FROM obligatory_field T2
WHERE T2.bill_datatype_id = T1.id AND T2.bill_sub_category_id = 1
)
This solution seems to work well, but this way I can not have any data from the second table, which might be needed in the future.
Do you have any suggestions on how to solve the problem with a LEFT JOIN? (The WHERE clause on the subcategory made it too challenging for me.)
Thank you for your help also in advance!
From how I understand your question, I think this query will achieve what you want:
SELECT T1.name
FROM bill_datatype T1
LEFT JOIN obligatory_field T2
ON T2.bill_datatype_id = T1.id AND T2.bill_sub_category_id = 1
WHERE T2.bill_datatype_id IS NULL
The WHERE condition on the JOIN'ed table will give you only the names from T1 which have no bill_sub_category_id or their bill_sub_category_id is not 1.
SQLFiddle
SELECT distinct T1.name
FROM
bill_datatype T1
right join
(
SELECT T2.bill_datatype_id
FROM obligatory_field T2
WHERE T2.bill_sub_category_id = 1
)
as T3
on T1.id != T3.bill_datatype_id
http://sqlfiddle.com/#!9/d4f616/18

inner join for a query?

I want to do a sql query and have some problems:
I want to salect from table_1 the ID's Where parent_id is the value I have:
SELECT ID FROM table_1 WHERE parent_ID = 'x'
I want to use the ID'S I got in 1. and
SELECT FROM table_2 WHERE ID = 'The ID's from Query 1.
Simple and Execute
Select t1.`id` FROM table t1 INNER JOIN table t2 ON t1.`id`=t2.`id`
As Bainternet mentioned you can do this with a subquery
SELECT * FROM table_2 WHERE ID IN (SELECT ID FROM table_1 WHERE parent_ID = 'x')
Though your idea to use an inner join is also good (especially since MySQL can be slow when processing subqueries).
SELECT t2.* FROM table_2 as t2 INNER JOIN table_1 AS t1 ON t2.ID = t1.ID WHERE t1.parent_ID = 'x'
If that's not clear, try looking at the MySQL JOIN Syntax or the Subqueries, as Bainternet mentioned. If these examples and the MySQL docs aren't clear enough for you, consider posting more details on exactly what you're trying to do (e.g. include table structures in your question). Also while you might want this information for some WordPress related work you are doing, there's nothing in the question itself that actually ties it to WordPress. So if you have more questions that about MySQL queries in general, then you might want to consider posting them to the StackOverflow, tagged as mysql-query.

SQL: How can we make a table1 JOIN table2 ON a table given in a field in table1?

Imagine I have table1 which has a column named 'table_name'. I use table1.table_name to store the name of another table in the database. The referenceable tables would all have a field 'target_id.
Is is possible to use table_name in a JOIN statement?
For example:
SELECT t1.*, t2.* FROM table1 AS t1
JOIN table1.table_name AS t2 ON t1.table1_id = t2.target_id
The obvious solution is to use the script (C++ in my case) to get the table name first, and construct a SQL query from it. The question is: can we bypass the script and do this directly in SQL (MySQL)?
Edit: What is dynamic SQL?
The only chance you have is to do 2 SQL statements:
select the tablename you need
use this table-name to dynamically build the secound query to get the data you need - what you want isn't possible to do with SQL directly (and it sounds like you've designed your database wrong in some way - but that's hard to say without knowing what's the goal of it).
I know I'm late to the party, but I wanted to offer a different solution. I see this sort of thing a lot in audit tables. The column table_name would refer to "what table was changed" and table1_id would refer to the ID of the row that changed in that table. In this case, the audit table is pointing back to many different tables that don't normally get joined.
Here goes:
SELECT t1.*, t2.*, t3.*, t4.*, t5.*
FROM table1 AS t1
left JOIN table2 AS t2
ON t1.table1_id = t2.target_id
and t1.table_name = 'table2'
left JOIN table3 AS t3
ON t1.table1_id = t3.target_id
and t1.table_name = 'table3'
left JOIN table4 AS t4
ON t1.table1_id = t4.target_id
and t1.table_name = 'table4'
left JOIN table5 AS t5
ON t1.table1_id = t5.target_id
and t1.table_name = 'table5'
Of course, the main drawback is that each table that can be possibly referenced needs to be explicitly included in the SQL command.
You can get more elegant output using this as your select list:
SELECT
t1.*,
coalesce(t2.fieldA, t3.fieldA, t4.fieldA, t5.fieldA) as fieldA,
coalesce(t2.fieldB, t3.fieldB, t4.fieldB, t5.fieldB) as fieldB
etc