SELECT * WHERE NOT EXISTS - mysql

I think I'm going down the right path with this one... Please bear with me as my SQL isn't the greatest
I'm trying to query a database to select everything from one table where certain cells don't exist in another. That much doesn't make a lot of sense but I'm hoping this piece of code will
SELECT * from employees WHERE NOT EXISTS (SELECT name FROM eotm_dyn)
So basically I have one table with a list of employees and their details. Then another table with some other details, including their name. Where there name is not in the eotm_dyn table, meaning there is no entry for them, I would like to see exactly who they are, or in other words, see what exactly is missing.
The above query returns nothing, but I know there are 20ish names missing so I've obviously not gotten it right.
Can anyone help?

You didn't join the table in your query.
Your original query will always return nothing unless there are no records at all in eotm_dyn, in which case it will return everything.
Assuming these tables should be joined on employeeID, use the following:
SELECT *
FROM employees e
WHERE NOT EXISTS
(
SELECT null
FROM eotm_dyn d
WHERE d.employeeID = e.id
)
You can join these tables with a LEFT JOIN keyword and filter out the NULL's, but this will likely be less efficient than using NOT EXISTS.

SELECT * FROM employees WHERE name NOT IN (SELECT name FROM eotm_dyn)
OR
SELECT * FROM employees WHERE NOT EXISTS (SELECT * FROM eotm_dyn WHERE eotm_dyn.name = employees.name)
OR
SELECT * FROM employees LEFT OUTER JOIN eotm_dyn ON eotm_dyn.name = employees.name WHERE eotm_dyn IS NULL

You can do a LEFT JOIN and assert the joined column is NULL.
Example:
SELECT * FROM employees a LEFT JOIN eotm_dyn b on (a.joinfield=b.joinfield) WHERE b.name IS NULL

SELECT * from employees
WHERE NOT EXISTS (SELECT name FROM eotm_dyn)
Never returns any records unless eotm_dyn is empty. You need to some kind of criteria on SELECT name FROM eotm_dyn like
SELECT * from employees
WHERE NOT EXISTS (
SELECT name FROM eotm_dyn WHERE eotm_dyn.employeeid = employees.employeeid
)
assuming that the two tables are linked by a foreign key relationship. At this point you could use a variety of other options including a LEFT JOIN. The optimizer will typically handle them the same in most cases, however.

You can also have a look at this related question. That user reported that using a join provided better performance than using a sub query.

Related

How to get data from multiple table

i have 3 table i m merge two table by join but cant Merge more then 3 table
multiple time
$query="select * from emp_table INNER JOIN emp_salary on emp_table.emp_id=emp_salary.emp_id";
how to get get three table data in singe table
A general pattern you might use here would be something like:
SELECT *
FROM emp_table emp
INNER JOIN emp_salary sal
ON emp.emp_id = sal.emp_id
INNER JOIN emp_address addr
ON emp.emp_id = addr.emp_id;
But note that in practice SELECT * should be avoided (I only used it because I don't know in which columns, from which tables, you are interested). Your actual PHP script should only select the columns you really need.

How to show name of position from second table based on number of rows in first table?

I have two tables "Employees" and "Positions"
I want to write a query that show the name of the Position that appears least in table "Employees" I have foreign key "ID_of_Position" in "Employees".
I came up with something like this, but it might not work:
SELECT Employees.ID_of_Position, Positions.ID_of_Position, Positions.Name_of_Position
FROM Positions
WHERE Employees.ID_of_Position in (SELECT ID_of_Position
FROM Employees
GROUP BY ID_of_Position
HAVING COUNT(ID_of_Position
)=1)
INNER JOIN Employees ON Positions.ID_of_Position = Employees.ID_of_Position;
The proper syntax would look like:
SELECT e.ID_of_Position, p.ID_of_Position, p.Name_of_Position
FROM Positions p JOIN
Employees e
ON p.ID_of_Position = e.ID_of_Position
WHERE e.ID_of_Position in (SELECT ID_of_Position
FROM Employees
GROUP BY ID_of_Position
HAVING COUNT(ID_of_Position) = 1
);
This doesn't answer the question (unless there is a position with exactly one employee), but it is at least syntactically correct.
It is important to understand that SELECT, FROM, and WHERE are all clauses in the SELECT statement. JOIN is an operator in the FROM clause.
At least where should be after join, and there is something with parentheses at the end ...
SELECT Employees.ID_of_Position, Positions.ID_of_Position, Positions.Name_of_Position
FROM Positions
INNER JOIN Employees ON Positions.ID_of_Position = Employees.ID_of_Position;
WHERE Employees.ID_of_Position in (SELECT ID_of_Position
FROM Employees
GROUP BY ID_of_Position
HAVING COUNT(ID_of_Position)=1
)

MySQL selecting from 2 or more tables, with a where clause that has a condition from table A in table B

I'm trying to do a select from 2 tables. However in table B I need to get a value from table A.
I'm simplifying this for the sake of ease, but the end result is a very complex query, and this is the only part thats causing problems.
In this example we're using 2 tables - one for members, one for the membership they are linked to.
Here's the code:
SELECT member.id member.name, member.email .membership.type, membership.status FROM
(
(SELECT * FROM tbl_members) AS member,
(SELECT * FROM tbl_memberships WHERE tbl_memberships.memberid = member.id) AS membership
)
The problem is that in the second select query, you cant access member.id, so how would you go about accessing information from the first query, in the second query, if this is even possible. If it isn't possible, what are the other options, bearing in mind a join cant return multiple columns.
But a join can return multiple columns:
SELECT *
FROM tbl_members m
JOIN tbl_memberships ms
ON ms.memberid = m.id
Why don't you use left join, if join is not returning all columns from tbl_members
SELECT *
FROM tbl_members
Left JOIN tbl_memberships
ON tbl_memberships.memberid = tbl_members.id

MySQL select rows that do not have matching column in other table

I can't seem to figure this out so far. I am trying to join two tables and only select the rows in table A that do not have a matching column in table B. For example, lets assume we have a users table and a sent table.
users table has the following columns: id, username
sent table has the following columns: id, username
I want to select all rows from users where username does not exist in sent table. So, if tom is in users and in sent he will not be selected. If he is in users but not in sent he will be selected. I tried this but it didn't work at all:
SELECT pooltest.name,senttest.sentname
FROM pooltest,senttest
WHERE pooltest.name != senttest.sentname
Typically, you would use NOT EXISTS for this type of query
SELECT p.Name
FROM pooltest p
WHERE NOT EXISTS (SELECT s.Name
FROM senttest s
WHERE s.Name = p.Name)
An alternative would be to use a LEFT OUTER JOIN and check for NULL
SELECT p.Name
FROM pooltest p
LEFT OUTER JOIN senttest s ON s.Name = p.Name
WHERE s.Name IS NULL
Note that the implicit join syntax you are using is considered obsolete and should be replaced with an explicit join.
Try this SQL:
SELECT users.username
FROM users
LEFT JOIN sent ON sent.username = users.username
WHERE sent.username IS NULL;
The better way in my opinion would be:
SELECT users.username
FROM users
LEFT JOIN sent ON sent.id = users.id
WHERE sent.id IS NULL;
As both the id fields, would be indexed (primary key I would have thought) so this query would be better optimised than the first one I suggested.
However you may find my first suggestion better for you, it depends on what your requirements are for your application.
May be this one can help you ....
I had also the same problem but Solved using this this query
INSERT INTO tbl1 (id,name) SELECT id,name from tbl2 where (name) not in(select name from tbl1);
hope this one will solve your problem

How do you do a mysql join where the join may come from one or another table

This is the query that I am using to match up a members name to an id.
SELECT eve_member_list.`characterID` ,eve_member_list.`name`
FROM `eve_mining_op_members`
INNER JOIN eve_member_list ON eve_mining_op_members.characterID = eve_member_list.characterID
WHERE op_id = '20110821105414-741653460';
My issue is that I have two different member lists, one lists are members that belong to our group and the second list is a list of members that do not belong to our group.
How do i write this query so that if a member is not found in the eve_member_list table it will look in the eve_nonmember_member_list table to match the eve_mining_op_members.characterID to the charName
I apologize in advance if the question is hard to read as I am not quite sure how to properly ask what it is that I am looking for.
Change your INNER JOIN to a LEFT JOIN and join with both the tables. Use IFNULL to select the name if it appears in the first table, but if it is NULL (because no match was found) then it will use the value found from the second table.
SELECT
characterID,
IFNULL(eve_member_list.name, eve_nonmember_member_list.charName) AS name
FROM eve_mining_op_members
LEFT JOIN eve_member_list USING (characterID)
LEFT JOIN eve_nonmember_member_list USING (characterID)
WHERE op_id = '20110821105414-741653460';
If you have control of the database design you should also consider if it is possible to redesign your database so that both members and non-members are stored in the same table. You could for example use a boolean to specify whether or not they are members. Or you could create a person table and have information that is only relevant to members stored in a separate memberinfo table with an nullable foreign key from the person table to the memberinfo table. This will make queries relating to both members and non-members easier to write and perform better.
You could try a left join on both tables, and then selecting the non-null results from the resulting query -
select * from
(select * from
eve_mining_op_members as x
left join eve_member_list as y1 on x.characterID = y1.characterID
left join eve_member_list2 as y2 on x.characterID = y2.characterID) as t
where t.name is not null
Or, you could try the same thing with a union and using inner join (assuming joined tables are the same):
select * from
(select * from eve_mining_op_members as x
inner join eve_member_list as y1 on x.characterID = y1.characterID
UNION
select * from eve_mining_op_members as x
inner join eve_member_list2 as y2 on x.characterID = y2.characterID) as t
You can throw in your op_id condition where you see fit (sorry, I didn't really understand where it came from). Good luck!
You have several options but by
using a UNION between the eve_member_list and eve_nonmember_member_list table
and JOIN the results of this UNION with your original eve_mining_op_members table
you will get your required results.
SQL Statement
SELECT lst.`characterID`
, lst.`name`
FROM `eve_mining_op_members` AS m
INNER JOIN (
SELECT characterID
, name
FROM eve_member_list
UNION ALL
SELECT characterID
, name
FROM eve_nonmember_member_list
) AS lst ON lst.characterID = m.characterID
WHERE op_id = '20110821105414-741653460';