SQL- listing people who did not contribute - mysql

I have an SQL task where it asks to "Show a list of persons with First Name and Last Name, who did not contribute in any composition."
Here is what I've attempted, but to no avail.
select * from (select count(a.person_id)num,a.first_name ||' '|| a.last_name name
from LABPRJ_PERSON a, LABPRJ_COMPOSITION_DETAIL w
where a.person_id=w.person_id group by last_name, a.first_name
union
select 0,a.first_name ||' '|| a.last_name name from LABPRJ_PERSON a where person_id not in (select person_id
from LABPRJ_COMPOSITION_DETAIL)) where num = 0;
Any help would be greatly appreciated.

You should just need this, as far as I can tell:
SELECT * FROM LABPRJ_PERSON WHERE person_id NOT IN (SELECT person_id FROM LABPRJ_COMPOSITION_DETAIL);

You can also use NOT EXISTS, it has better performance than NOT IN:
SELECT last_name, first_name FROM LABPRJ_PERSON p
WHERE NOT EXISTS
(SELECT * FROM LABPRJ_COMPOSITION_DETAIL c ON c.person_id = p.person_id)

IF YOU ARE USING SQL SERVER PLEASE TRY THIS ONE.
SELECT
CAST(A.FIRST_NAME AS AS VARCHAR(MAX)) + ' '+ CAST(A.LAST_NAME AS VARCHAR(MAX))
FROM
LABPRJ_PERSON A
WHERE NOT EXISTS
(
SELECT
B.PERSON_ID
FROM
LABPRJ_COMPOSITION_DETAIL B WHERE A.PERSON_ID = B.PERSON_ID
)

SELECT last_name, first_name
FROM LABPRJ_PERSON AS T1
RIGHT OUTER JOIN
LABPRJ_COMPOSITION_DETAIL AS T2
ON T1.person_id=T2.person_id
WHERE T2.person_id IS NULL;

Related

SQL - Get the names instead of ID

I have a table called tbl_appointment which has 2 foreign keys: idclient and idemployee which they are referencing tbl_persons.
So what i want to do is instead of getting the id of idclient and idemployee, i want to get the names (name,last_name,last_sname) which they belong to those id.
Query
SELECT CONCAT(tbl_persons.name,' ',tbl_persons.last_name,' ',tbl_persons.last_sname) as fullname, tbl_appointment.*
FROM tbl_appointment
INNER JOIN tbl_persons ON tbl_persons.idpersons = tbl_appointment.idemployee
INNER JOIN tbl_persons ON tbl_persons.idpersons = tbl_appointment.idclient
WHERE idclient= '$user';
You can use the following query, using a LEFT JOIN instead of INNER JOIN:
SELECT
CONCAT(p1.name, ' ', p1.last_name, ' ', p1.last_sname) AS client_fullname,
CONCAT(p2.name, ' ', p2.last_name, ' ', p2.last_sname) AS employee_fullname
FROM tbl_appointment ta
LEFT JOIN tbl_persons p1 ON ta.idclient = p1.idpersons
LEFT JOIN tbl_persons p2 ON ta.idemployee = p2.idpersons
WHERE ta.idclient = '$user'
Try the following
SELECT
app.*,
CONCAT(client.name,' ',client.last_name,' ',client.last_sname) AS client_full_name,
CONCAT(empl.name,' ',empl.last_name,' ',empl.last_sname) AS empl_full_name
FROM tbl_appointment app
LEFT JOIN tbl_persons client ON app.idclient=client.id
LEFT JOIN tbl_persons empl ON app.idemployee=empl.id
WHERE app.idclient= '$user'
Try the following code: Only thing is you have to select the clients and employees separately, together is more difficult
SELECT name,last_name,last_sname
FROM tbl_persons WHERE id IN (
SELECT DISTINCT idclient FROM tbl_appointment;
); -- This will select all the clients
SELECT name,last_name,last_sname
FROM tbl_persons WHERE id IN (
SELECT DISTINCT idemployee FROM tbl_appointment;
); -- This will select all the employees

How to write sql query for FIlter country as status wise

Here I have a simple table. I would like to end up with a table like the one given. What is the best way to write the sql statement to achieve this?
Table 1
Id Name Approved
1 Australia 3
2 UAE 1
3 India 2
Table 2
Id Status
1 Submit
2 In-Progress
3 Pending
Show result as
Submitted In-Progress Pending
UAE India Australia
Please Try below query:
create table #country
(
ID int identity(1,1),
Name varchar(30),
Approved int
)
create table #status
(
ID int,
Status varchar(30)
)
insert into #country (Name, Approved) values ('Australia',3), ('UAE',1), ('India',2)
insert into #status (ID, Status) values (1,'Submit'), (2, 'In-Progress'), (3,'Pending')
select Submit, [In-Progress],[Pending]
from (
select t1.Name, t2.Status
from #country t1
inner join #status t2 on t1.Approved = t2.ID
)dd1
pivot (
max(Name) for Status in ([Submit], [In-Progress],[Pending])
) piv
drop table #country
drop table #status
Output of this query:
Try this:-
select
trim(replace(group_concat(submitted),',',' ')) as submitted,
trim(replace(group_concat(InProgress),',',' ')) as InProgress,
trim(replace(group_concat(Pending),',',' ')) as Pending
from
(
Select
case when status='Submit' then A.Name else ' ' end as submitted,
case when status='In-Progress' then A.Name else ' ' end as InProgress,
case when status='Pending' then A.Name else ' ' end as Pending
FROM
TABLE1 A
INNER JOIN
TABLE2 B
ON A.ID=B.ID
) a;
Here's the answer as of given Data:
select `Submit`,`In-Progress`,`Pending` from
(select `Submit`,`In-Progress`,INP.id from
(select Name as 'Submit',a.id from
(select * from table1)as a
LEFT JOIN
(select * from table2) as b
on a.Approvide = b.`Id`
where b.`STATUS` = 'Submit') as Sub
INNER JOIN
(select Name as 'In-Progress',a.id from
(select * from table1)as a
LEFT JOIN
(select * from table2) as b
on a.Approvide = b.`Id`
where b.`STATUS` = 'In-Progress') as INP
on Sub.id != INP.id) as c
INNER JOIN
(select Name as Pending,a.id from
(select * from table1)as a
LEFT JOIN
(select * from table2) as b
on a.Approvide = b.`Id`
where b.`STATUS` = 'Pending') as Pen
on c.id != Pen.id
select Name,Status from Table1 natural join Table2;
That's simple. The result should look like this now. I think this is usual approach that how we actually retrieve the information from multiple tables.
Name Status
Australia Pending
UAE Submit
India In-Progress
Please consider

SQL Query: list of all maximal reservers

I have the following schemas:
sailor: ssn, fname, lname, address
reservation: sailor_ssn, date_reserved, boat_reg#
boat: reg#, bname, color, model#
I want to list the names of all maximal reservers. A sailor is a maximal reserver if the set of boat(s) he has reserved is not a proper subset of any other sailors.
Thanks in advance
I came up with the following query:
SELECT p.fname, p.lname
FROM sail.person p
JOIN sail.sailor s ON p.ssn = s.ssn
JOIN
(SELECT DISTINCT r4.sailor_ssn
FROM sail.reservation r4
WHERE r4.sailor_ssn NOT IN
(SELECT T3.sailor_ssn
FROM
(SELECT *
FROM
(SELECT r1.sailor_ssn, r2.sailor_ssn sssn, count(*) ctr1
FROM sail.reservation r1
JOIN sail.reservation r2 ON r1.boat_reg# = r2.boat_reg#
AND r1.sailor_ssn != r2.sailor_ssn
GROUP BY r1.sailor_ssn, r2.sailor_ssn) T1
JOIN
(SELECT r3.sailor_ssn rssn, count(*) ctr2
FROM sail.reservation r3
GROUP BY r3.sailor_ssn) T2
ON T1.sailor_ssn = T2.rssn) T3
where T3.ctr1 = T3.ctr2)) T4
ON T4.sailor_ssn = s.ssn;
Is there any better solution?

SQL Joins to Get Monthly Total Wages from Three Tables

I need to get empolyees info from employees table, and their total wages from two different tables.
The SQL is approximately like this, but I don't really know how to use joins to do this:
CONCAT(first_name, ' ', last_name) from employees as e
Sum(hours*pay) where date is "THIS MONTH" and employee_id = e.id from taxed_work
Sum(hours*pay) where date is "THIS MONTH" and employee_id = e.id from nontaxed_work
I am not sure how to join these together properly. I don't want to see any of the employees that have not done either kind of work for the month, only those who have. I'm using mysql and will put the data in a table with php
If anyone could tell me how to do the "THIS MONTH" part that would be cool too. Just being lazy on that part, but figured while I was here...
Thanks for the help!
You could use correlated subqueries:
select concat(first_name, ' ', last_name)
, (
select sum(hours*pay)
from taxed_work tw
where tw.employee_id = e.id
and year(tw.date) = year(now())
and month(tw.date) = month(now())
)
, (
select sum(hours*pay)
from nontaxed_work ntw
where ntw.employee_id = e.id
and year(ntw.date) = year(now())
and month(ntw.date) = month(now())
)
from employees e
You can calculate their totals inside subquery.
SELECT a.id ,
CONCAT(first_name, ' ', last_name) FullName,
b.totalTax,
c.totalNonTax,
FROM employees a
LEFT JOIN
(
SELECT employee_id, Sum(hours*pay) totalTax
FROM taxed_work
WHERE DATE_FORMAT(`date`,'%c') = DATE_FORMAT(GETDATE(),'%c')
GROUP BY employee_id
) b ON b.employee_id = a.id
LEFT JOIN
(
SELECT employee_id, Sum(hours*pay) totalTax
FROM nontaxed_work
WHERE DATE_FORMAT(`date`,'%c') = DATE_FORMAT(GETDATE(),'%c')
GROUP BY employee_id
) c ON c.employee_id = a.id
Try this query.
select
CONCAT(first_name, ' ', last_name) as employee_name,
sum(case when t.this_date = 'this_month' then t.hours*t.pay else 0 end),
sum(case when n.this_date = 'this_month' then t.hours*t.pay else 0 end)
from employees e
left join taxed_work t on e.id = t.employee_id
left join nontaxed_work n on e.id = n.employee_id
group by (first_name, ' ', last_name)
Please replace the t.this_date and n.this_date fields with actual field names as I am not aware of the exact table structure. Also, replace the "this_month" value as per your need.

MYSQL IN substitute

Good day
I am trying to query the names of employees who work on every project.
My code is as follows:
SELECT CONCAT (fname,' ', minit,'. ' , lname) AS NAME
FROM employee a, works_on b, project c
WHERE pno IN (Select pnumber //WHAT COULD I SUBSTITUTE W/ IN
FROM projet)
AND a.ssn = b.essn
AND b.pno = c.pnumber
The problem with IN is that it is that the values inside are like evaluated as 'OR'... what is the equivalent of IN that makes the value of my subquery evaluated like 'AND'
Thank you in advance.
EDIT:
As reqeusted..
SELECT *
FROM employee e
WHERE NOT EXISTS
(
SELECT NULL
FROM employee ei
CROSS JOIN
project p
LEFT JOIN
works_on wo
ON wo.pno = p.pnumber
AND wo.essn = ei.ssn
WHERE ei.ssn = e.ssn
)
select CONCAT (fname,' ', minit,'. ' , lname) AS NAME
from employee
left join works_on
on works_on.essn=employee.ssn
group by employee.ssn
having count(works_on.essn) = (select count(*) from project);
Simplified example:
create table emp_work_on
(
emp_name varchar(50),
work_on varchar(30)
);
create table works
(
work_on varchar(30)
);
insert into works(work_on) values('apple'),('microsoft'),('google'),('facebook')
insert into emp_work_on values
('john','apple'),('john','microsoft'),('john','google'),('john','facebook'),
('paul','microsoft'),('paul','google'),
('george','apple'),('george','microsoft'),('george','google'),('george','facebook'),
('ringo','apple'),('ringo','facebook');
select e.emp_name
from works w
left join emp_work_on e on e.work_on = w.work_on
group by e.emp_name
having count(e.work_on) = (select count(*) from works)
order by e.emp_name
Output:
emp_name
----------
george
john
(2 rows)
On your table structure, you could use this:
SELECT * FROM employee
WHERE ssn IN
(
SELECT w.essn
FROM project c
LEFT JOIN works_on w ON w.pno = c.pnumber
GROUP BY w.essn
HAVING COUNT(w.pno) = (SELECT COUNT(*) FROM project)
)
Hmm.. but I think this could be the simplest, granting there's no repeating pno on employee's works_on, i.e. there's no pno in works_on that doesn't exists on project, i.e. referential integrity is maintained
SELECT * FROM employee
WHERE ssn IN
(
SELECT essn
FROM works_on
GROUP BY essn
HAVING COUNT(pno) = (SELECT COUNT(*) FROM project)
)