"!= nor <>" doesn't work when selecting data with subquery - mysql

i have table employee:
And what I want to select is list of employees who do not have a designated chief who works in the same department (employee #24 have chief from another department and some ppl doesn't have chief at all)
So here is the question:
Why this works:
SELECT
*
FROM
employee a
WHERE
a.cheif_id NOT IN (SELECT
cheif_id
FROM
employee b
WHERE
b.dep_id = a.dep_id
AND b.id = a.cheif_id);
but this does not:
SELECT
*
FROM
employee a
WHERE
a.cheif_id <> (SELECT
cheif_id
FROM
employee b
WHERE
b.dep_id = a.dep_id
AND b.id = a.cheif_id);
In addition if we want to select employees who Do have a designated chief who works in the same department '=' and 'in ()' works.
Sorry for cheif mistake.

if there are multiple data in your Subquery,you can't use <>,you can use NOT IN
I think you can use JOIN instead of subquery
SELECT e1.name chiefname,e2.*
FROM employee e1
INNER JOIN e2
ON e1.dep_id = e2.dep_id AND e1.id = e2.cheif_id

Related

Query the Latest Data Based On Condition in Multiple Columns and Concat Them

I have a database like this
employees
I try to query the latest job and salary for every employees based on latest s_from_date and t_from_date and concat it to one column "Current Employees"
I try to filter it with max(s_from_date) and max(t_from_date) but it didn't work
SELECT CONCAT (first_name,' ',last_name,' ',salary,' ',title) As "Current Employees"
FROM employees WHERE s_from_date = (SELECT MAX(s_from_date) FROM employees) AND t_from_date = (SELECT MAX(t_from_date) FROM employees);
if you use phpmyadmin, it can tell where the error position, please see image bellow.
I think you missed "(" after "concat".
SELECT CONCAT(first_name,' ',last_name,' ',salary,' ',title) As Current Employees
FROM employees WHERE s_from_date = (SELECT MAX(from_date) FROM employees) AND t_from_date = (SELECT MAX(from_date) FROM employees)
You could try
SELECT CONCAT(first_name,' ',last_name,' ',salary,' ',title) As "Current Employees"
FROM employees e1
WHERE s_from_date = (SELECT MAX(s_from_date) FROM employees e2
WHERE e2.first_name = e1.first_name AND e2.last_name = e1.last_name)
AND t_from_date = (SELECT MAX(t_from_date) FROM employees e3
WHERE e3.first_name = e1.first_name AND e3.last_name = e1.last_name);
If your employees table has id/employee_id column, instead of using last_name and first_name in condition of 2 subqueries, you could change it to e2.id = e1.id, e3.id = e1.id.

SQL query to compare a particular column to the average of the same coloum

My Schema is as follows
doctor (doctor_name, residence_address, postal_code, year_experience)
works (doctor_name, branch_name, annual_pay)
branch (branch_name, branch_address, postal_code)
patient (patient_name, doctor_name, branch_name)
I have been asked to retrieve the doctor_name whose annual pay is more than the average of all the doctors in a branch_name called "Singapore"
How do i do that in an sql query. Im using MySQL and so far i have tried this
SELECT doctor.doctor_name, doctor.residence_address
FROM doctor INNER JOIN works on doctor.doctor_name = works.doctor_name
WHERE avg(annual_pay)< annual pay
Try below query:
SELECT doctor_name
FROM doctor
INNER JOIN works ON doctor.doctor_name = works.doctor_name
WHERE annual_pay > (
SELECT avg(annual_pay)
FROM works
)
AND branch_name = 'Singapore'
One of possible solution is
select doctor_name
from
works,
(select avg(annual_pay) ap from works where branch_name='Singapore') ap
where
annual_pay>ap.ap
Just compare pay with calculated avg from a sub-query
SELECT doctor_name, annual_pay
FROM works
WHERE annual_pay > (SELECT AVG(annual_pay)
FROM works
WHERE branch_name = 'Singapore')
AND branch_name = 'Singapore'

SQL select by qualifying multiple strings

I have to find student names who are enrolled in a class AND also in another class. But when I do a WHERE statement it cuts out out all the other lines that have the other classes.
So my question is: How would I go about doing it so that it compares the entire group and only selects students that are both in CLASSA and CLASSB.
Some of the students are in CLASSA and some of them are in CLASSB and some are in both. How do I get the one that is in both?
For example:
John Smith is in CLASSA
BETTY WHITE is in CLASSB
Timmy Edwards is in CLASSA
Timmy Edwards is in CLASSB
If I use an OR, it will select all of the names. But I only want a student that is in BOTH classes. So Timmy Edwards is the one I want selected.
WHERE C.DESCRIPTION LIKE 'Systems Analysis%'
AND C.DESCRIPTION LIKE 'Project Management%'
You can do use group by and having:
select student
from enrollments
where class in ('CLASSA', 'CLASSB')
group by student
having count(*) = 2;
This version assumes that a student can be enrolled only once for a given class.
No individual row will every have information for both classes. That means that AND and OR as you're using them are useless. You need to check for the existence of such rows using the EXISTS keyword.
select distinct
student
from
enrollments
where
exists (
select
1
from
enrollments e1
where
e1.student = enrollments.student
and e1.class = 'CLASSA'
) and exists (
select
1
from
enrollments e2
where
e2.student = enrollments.student
and e2.class = 'CLASSB'
)
Note:
Each row will have the student name in it, so I've added the DISTINCT keyword to remove the duplicates.
You could try something like this, (although im not sure what exactly your schema is like...)
WITH a AS
(
SELECT
S.FIRST_NAME||' '||S.LAST_NAME [Student]
,C.DESCRIPTION
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)
WHERE C.DESCRIPTION = 'CourseA'
)
,b AS
(
SELECT
S.FIRST_NAME||' '||S.LAST_NAME [Student]
,C.DESCRIPTION
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)
WHERE C.DESCRIPTION = 'CourseB'
)
Select a.Student, a.Description [DescA], b.Description [DescB]
from a join b on a.Student = b.Student
--optional where to just get students in both classes...
where a.Description is not null and b.Description is not null
Hope this assists...
You can always try the neat trick of joining a SELECT result with itself and then selecting from that result.
SELECT A.NAME
FROM (SELECT S.FIRST_NAME||' '||S.LAST_NAME as NAME,
S.STUDENT_ID as S_ID,
C.DESCRIPTION as DESC
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)) A
JOIN (S.STUDENT_ID as S_ID, C.DESCRIPTION as DESC
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)) B
ON A.S_ID = B.S_ID
WHERE A.DESC LIKE 'Systems Analysis%'
AND B.DESC LIKE 'Project Management%'
GROUP BY A.NAME

SQL query for matching multiple values in the same column

I have a table in MySQL as follows.
Id Designation Years Employee
1 Soft.Egr 2000-2005 A
2 Soft.Egr 2000-2005 B
3 Soft.Egr 2000-2005 C
4 Sr.Soft.Egr 2005-2010 A
5 Sr.Soft.Egr 2005-2010 B
6 Pro.Mgr 2010-2012 A
I need to get the Employees who worked as Soft.Egr and Sr.Soft.Egr and Pro.Mgr. It is not possible to use IN or Multiple ANDs in the query. How to do this??
One way:
select Employee
from job_history
where Designation in ('Soft.Egr','Sr.Soft.Egr','Pro.Mgr')
group by Employee
having count(distinct Designation) = 3
What you might actually be looking for is relational division, even if your exercise requirements forbid using AND (for whatever reason?). This is tricky, but possible to express correctly in SQL.
Relational division in prosa means: Find those employees who have a record in the employees table for all existing designations. Or in SQL:
SELECT DISTINCT E1.Employee FROM Employees E1
WHERE NOT EXISTS (
SELECT 1 FROM Employees E2
WHERE NOT EXISTS (
SELECT 1 FROM Employees E3
WHERE E3.Employee = E1.Employee
AND E3.Designation = E2.Designation
)
)
To see the above query in action, consider this SQLFiddle
A good resource explaining relational division can be found here:
http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division
If you need to get additional information back about each of the roles (like the dates) then joining back to your original table for each of the additional designations is a possible solution:
SELECT t.Employee, t.Designation, t.Years, t1.Designation, t1.Years, t2.Designation, t2.Years
FROM Table t
INNER JOIN t2 ON (t2.Employee = t.Employee AND t2.Designation = 'Sr.Soft.Egr')
INNER JOIN t3 ON (t3.Employee = t.Employee AND t3.Designation = 'Soft.Egr')
WHERE t.Designation = 'Pro.Mgr';
Why not the following (for postgresql)?
SELECT employee FROM Employees WHERE Designation ='Sr.Soft.Egr'
INTERSECT
SELECT employee FROM Employees WHERE Designation ='Soft.Egr'
INTERSECT
SELECT employee FROM Employees WHERE Designation ='Pro.Mgr'
Link to SQLfiddle
I know this might not optimized, but I find this much much easier to understand and modify.
Try this query:
SELECT DISTINCT t1.employee,
t1.designation
FROM tempEmployees t1, tempEmployees t2, tempEmployees t3
WHERE t1.employee = t2.employee AND
t2.employee = t3.employee AND
t3.employee = t1.employee AND
t1.designation != t2.designation AND
t2.designation != t3.designation AND
t3.designation != t1.designation

Mysql insert records from table A to table B. if table B.column is less than

**Employee**
PK empId
firstName
lastName
isRegularEmp
**Employee_Training**
PK FK empId
PK FK trainingId
logId
**Training**
PK TrainingId
date
specialEmployeesNeeded
regularEmployeesNeeded
FK roomId
I am trying to insert all the employees into the employee_training table by a specific date. It works except that I have a required amount not to surpass which is the SpecialEmployees/ Regular Employees field value.
For instance I have 200 Regular Employees and 100 Regular Employees in the Employee Table but I only need 35 Special Employees and 5 Reegular Employees to be inserted as specified in the training table.
I tried HAVING but it keeps throwing an error unknown column. Please help, I tried inserting one type of employee , but it still doesn't work
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= regularEmployeesNeeded
I can't post my erd because I don't have enough points.
regularEmployees is not a column in any of your tables nor is it defined anywhere in your query. Try
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= (select count(*) from EMPLOYEE where isRegularEmp=true )
The placement of your isRegularEmp condition is incorrect. It should be placed in the WHERE clause.
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= regularEmployees
EDIT: As pointed out in Michael Benjamin's answer, regularEmployees is not a field is not defined. You need to SELECT the COUNT of regular employees.
INSERT INTO EMPLOYEE_TRAINING(empId, trainingId)
SELECT E.empId , T.TrainingId
FROM EMPLOYEE E, TRAINING T
WHERE T.`date` = "2013-4-20"
AND E.isRegularEmp = false
HAVING COUNT(E.empId) <= (SELECT COUNT(*) FROM EMPLOYEE WHERE isRegularEmp = true)