I have one table that contains first name and last name of employees in my company, and a field that determines whether they are still working for the company.
I have another table with contains list of tasks for the employees - It also contains two field with first and last name of the employee (- and yes, I know that's not a good structure).
I want to be able to find all employees that are still working for the company but have no tasks using MySQL query.
Any ideas?
SELECT *
FROM employees
WHERE still_working_for_company
AND NOT EXISTS (
SELECT TRUE
FROM tasks
WHERE tasks.firstname = employees.firstname
AND tasks.lastname = employees.lastname
)
You can try this--
select * from FirstTable where firstTable.employee='yes' and
firstTable.empid IN (select secondTbl.empId where firstTable.empid = secondTbl.empId)
Query is not tested and assume that your second table (task table) contain employee data only when task is assign.
Try this:
SELECT e.*
FROM emp e
LEFT JOIN emptask et ON e.firstname = et.firstname AND e.lastname = et.lastname
WHERE e.stillworks = 'y' AND et.taskid IS NULL
GROUP BY e.firstname, e.lastname
Related
Let's consider a toy example. There is a table employees and table tasks, where each task is assigned to one employee. One employee can have multiple tasks.
I want to query employees filtering them by some columns in their tasks. I group the employees to display each one only once. The query would be something like this:
SELECT *
FROM employees emp JOIN tasks tsk on emp.id = tsk.assigned_emp
WHERE tsk.deadline = today
GROUP BY employees
This works fine, but now let's say that I'd like to select the employees that don't have any tasks which deadline is due today. My first try was:
tsk.deadline != today
but then is finds employees with at least one task that is not due today. How to write a query to include all possible tasks for a given employee?
There are several different solutions for this antijoin task. One of them is using NOT EXISTS
SELECT *
FROM employee e
WHERE NOT EXISTS(
SELECT 1
FROM tasks t
WHERE e.id = t.assigned_emp and t.deadline = today
)
You want the LEFT JOIN ... IS NULL pattern for this.
SELECT *
FROM employees emp
LEFT JOIN tasks tsk ON emp.id = tsk.assigned_emp
AND tsk.deadline = today
WHERE tsk.deadline IS NULL
GROUP BY employees
JOIN removes rows from its first table that don't match your ON condition. By contrast, LEFT JOIN leaves them in place putting NULL values into the result columns from the second table.
I have 2 tables, 1 called Employee and 1 called Salary. Employee table consists of Emp_Name, Emp_Address, Emp_ID & Salary table consists of Salary_Details and Emp_ID. > Can you write down a query for retrieving the Salary_Details of 1 of the employee based on last name using Inner Join?
I am not sure what you are looking for, but this might help you:
SELECT * FROM Employee e
INNER JOIN Salary s ON e.Emp_ID = s.Emp_ID
WHERE e.Emp_Name = 'EMPLOYEENAME'
That will give you back all fields from Employee and Salary for an Employee with the name = 'EMPLOYEENAME' (which you can exchange then).
You can adjust the columns returned as needed depending on your app...
SELECT e.Emp_Name, e.Emp_ID, s.Salary_Details
FROM Employee e
INNER JOIN Salary s USING (Emp_ID)
WHERE e.Emp_Name = 'Smith';
The USING keyword is kind of obscure and works only if the join column is named identically in both tables. The previous answer with ON instead of USING will work in all cases. I like USING as a personal preference.
I have 3 tables: Emplyees, Jobs and Departments
What I'm trying to achieve is to get the number of emplyees from one department.
I tried something:
SELECT count(Emplyees.id) FROM Emplyees
INNER JOIN Job ON (Job.id = Emplyees.job_id)
INNER JOIN Department ON (Department.id = 2)
but it returns the number of emplyees from all departments.
Any advice please?
An EXISTS clause will allow you to limit by the existence of something without having to worry about whether or not an employee also has other jobs, which will keep your count easy to figure.
Also, since the only thing you need from the department is the id, you can leave that table out and just filter by the dept_id field of the Job table.
SELECT count(id)
FROM Employees
WHERE EXISTS (
SELECT 1
FROM Job
WHERE id = Employees.job_id
AND dept_id = 2
)
Use WHERE clause to filter out department,where clause will apply for the whole result set returned by joins,while condition in on clause will filter result from joined table only
SELECT count(e.id)
FROM Emplyees e
INNER JOIN Job j ON (j.id = e.job_id)
INNER JOIN Department d ON (j.dept_id =d.id )
WHERE d.id = 2
And also use DISTINCT in count so if any employee has applied on multiple jobs that belong to same department will be counted as 1 i.e COUNT(DISTINCT e.id)
I was wondering how this query works:
SELECT empname FROM Employee WHERE not exists (
SELECT projid FROM Project WHERE not exists (
SELECT empid, projid FROM Assigned WHERE empid = Employee.empid and projid = Project.projid
)
)
It is supposed to return names of all employees who are assigned to every project and it does work however I am getting confused as to how/why it works correctly.
Schema is:
Employee(empID INT,empName VARCHAR(100),job VARCHAR(100),deptID INT,salary INT);
Assigned(empID INT,projID INT,role VARCHAR(100));
Project(projID INT,title VARCHAR(100),budget INT,funds INT);
I am new to SQL so a detailed/simple explanation would be appreciated.
When I need to try to understand what's going on, I look for the inner-most query and work my way outwards. In your case, let's start with:
SELECT empid, projid
FROM Assigned
WHERE empid = Employee.empid and projid = Project.projid
This is matching all records in the Assigned table where the empid and projid are in the previous tables (hence the Employee.empid and Project.projid).
Assume there are 5 projects in the Projects table and Employee1 is assigned to each. That would return 5 records. Also assume Employee2 is assigned to 1 of those projects, thus returning 1 record.
Next look at:
SELECT projid FROM Project WHERE not exists (
...
)
Now this says for those found records in the previous query (Employee1 with 5 projects and Employee2 with 1 project), select any projid from the Project table where there aren't any matches (not exists) from the previous query. In other words, Employee1 would return no projects from this query but Employee2 would return 4 projects.
Finally, look at
SELECT empname FROM Employee WHERE not exists (
...
)
Just as with the 2nd query, for any records found in the previous query (no records to match those employees with all projects such as Employee1 and some records if the employee isn't assigned to every project such as Employee2), select any employee from the Employee table where there aren't any matches (again, not exists). In other words, Employee1 would return since no projects were returned from the previous query, and Employee2 would not return, since 1 or more projects were returned from the previous query.
Hope this helps. Here's some additional information about EXISTS:
http://dev.mysql.com/doc/refman/5.0/en/exists-and-not-exists-subqueries.html
And from that article:
What kind of store is present in all cities?
SELECT DISTINCT store_type FROM stores s1 WHERE NOT EXISTS (
SELECT * FROM cities WHERE NOT EXISTS (
SELECT * FROM cities_stores
WHERE cities_stores.city = cities.city AND cities_stores.store_type = stores.store_type));
The last example is a double-nested NOT EXISTS query. That is, it has
a NOT EXISTS clause within a NOT EXISTS clause. Formally, it answers
the question “does a city exist with a store that is not in Stores”?
But it is easier to say that a nested NOT EXISTS answers the question
“is x TRUE for all y?”
Good luck.
A NOT EXISTS (subquery) predicate will return TRUE when the resultset from the subquery has no rows. It will return FALSE when a matching row is found.
Essentially, the query is asking
for each row in Employee... check each row from the Project table, to see if there is a row in the Assigned table for a row that has an empid that matches the empid on the Employee row and a projid that matches a row in the Project table.
The row from Employee will be returned only if no matching row is found.
Note that the expressions in the SELECT list of the subquery are not important; all that is being checked is whether that subquery returns one (or more) rows or not. Normally, we use a literal 1 in the SELECT list; that remind us that what we are checking is whether a row is found or not.)
I would typically write that query in a style that looks like this:
SELECT e.empname
FROM Employee e
WHERE NOT EXISTS
( SELECT 1
FROM Project p
WHERE NOT EXISTS
( SELECT 1
FROM Assigned a
WHERE a.empid = e.empid
AND a.projid = p.projid
)
)
And I read the "SELECT 1" as "select one row")
The resultset from that query is essentially equivalent to the resultset from this (usually much less efficient) query:
SELECT e.empname
FROM Employee e
WHERE e.empid NOT IN
( SELECT a.empid
FROM Assigned a
JOIN Project p
ON a.projid = p.projid
WHERE a.empid IS NOT NULL
GROUP
BY a.empid
)
The NOT IN query can be a little easier to understand, because you can run that subquery and see that it returns something. (What can be kind of confusing about the NOT EXISTS subquery is that it doesn't matter what expressions are returned in the SELECT list; what matters is whether a row is returned or not.) There are some "gotchas" with the NOT IN subquery besides really bad performance; you need to be careful to ensure that the subquery does not return a NULL value, because then the NOT IN (NULL,...) will never return true.
An equivalent resultset can be returned using an anti-join pattern as well:
SELECT e.empname
FROM Employee e
LEFT
JOIN ( SELECT a.empid
FROM Assigned a
JOIN Project p
ON a.projid = p.projid
WHERE a.empid IS NOT NULL
GROUP
BY a.empid
) o
ON o.empid = e.empid
WHERE o.empid IS NULL
In that query, we are looking for "matches" on empid. The LEFT keyword tells MySQL to also return any rows from Employee (the table one the left side of the JOIN) which do not have a match. For those rows, a NULL value is returned in place of the values of the columns that would have been returned if there had been a matching row. The "trick" is then to throw out all the rows that matched. We do that by checking for a NULL in a column that would not be NULL if there had been a match.
If I were going to write this query using a NOT EXISTS predicate, I would probably actually favor writing it like this:
SELECT e.empname
FROM Employee e
WHERE NOT EXISTS
( SELECT 1
FROM Assigned a
JOIN Project p
ON a.projid = p.projid
WHERE a.empid = e.empid
)
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.