Having hard time understanding SQL Query - sql

I ran across this query and having hard time understanding what it does
SELECT DISTINCT
EMPLOYEE.EMPLOYEE_ID,
EMPLOYEE.LAST_NAME,
EMPLOYEE.FIRST_NAME,
COUNT(*)
FROM EMPLOYEE
JOIN ENTRY ON EMPLOYEE.EMPLOYEE_ID = ENTRY.EMPLOYEE_ID
JOIN TICKET ON ENTRY.TICKET_ID = TICKET.TICKET_ID
WHERE ENTRY.ACTIVITY_ID = 'ADVTS' AND EMPLOYEE.DEPARTMENT_ID ='SLS'
GROUP BY EMPLOYEE.EMPLOYEE_ID, EMPLOYEE.LAST_NAME,
EMPLOYEE.FIRST_NAME,ENTRY.ENTRY_ID
HAVING COUNT(ENTRY.ENTRY_ID) >=
(SELECT CAST(1.25 * COUNT(ENTRY.ACTIVITY_ID)/COUNT(DISTINCT EMPLOYEE.EMPLOYEE_ID) AS float)
FROM
EMPLOYEE
JOIN
ENTRY ON EMPLOYEE.EMPLOYEE_ID = ENTRY.EMPLOYEE_ID
WHERE
ENTRY.ACTIVITY_ID = 'ADVTS' AND EMPLOYEE.DEPARTMENT_ID = 'SLS')
As far as I understand it gives a list of EMPLOYEEs who done ADVTS ACTIVITY and from DEPARTMENT SLS which made ENTRYs at least as much as Average entries made in the DEPARTMENT SLS for ADVTS purposes
Thanks to anyone who take their time to help
Edit succesful result after comments:
SELECT
EMPLOYEE.EMPLOYEE_ID,
EMPLOYEE.LAST_NAME,
EMPLOYEE.FIRST_NAME
FROM EMPLOYEE
JOIN
ENTRY ON ENTRY.EMPLOYEE_ID = EMPLOYEE.EMPLOYEE_ID
GROUP
BY EMPLOYEE.EMPLOYEE_ID, EMPLOYEE.LAST_NAME,
EMPLOYEE.FIRST_NAME
HAVING
COUNT(ENTRY.ENTRY_ID) >=
(SELECT
CAST(1.25 *
COUNT(ENTRY.ACTIVITY_ID)/COUNT(DISTINCT EMPLOYEE.EMPLOYEE_ID)AS float)
FROM
EMPLOYEE JOIN ENTRY ON EMPLOYEE.EMPLOYEE_ID = ENTRY.EMPLOYEE_ID
WHERE
ENTRY.ACTIVITY_ID = 'ADVTS' AND EMPLOYEE.DEPARTMENT_ID = 'SLS')
OUTPUT:
EMPLOYEE_ID| LAST_NAME| FIRST_NAME
7 | Salesman | Efficient

Assuming that TICKET_ID is unique in Ticket and is never NULL in ENTRY, then you can get rid of that JOIN.
Then I assume the purpose of the query is to return employees whose count is more than 1.25 the overall average. That requires a few more (reasonable) assumptions, but this is more simply written as:
SELECT e.*
FROM (SELECT EM.EMPLOYEE_ID, EM.LAST_NAME, EM.FIRST_NAME, COUNT(*) AS CNT,
SUM(COUNT(*)) OVER () * 1.0 / COUNT(*) OVER () as AVG_CNT
FROM EMPLOYEE EM JOIN
ENTRY EM
ON EM.EMPLOYEE_ID = EN.EMPLOYEE_ID
WHERE EN.ACTIVITY_ID = 'ADVTS' AND EM.DEPARTMENT_ID = 'SLS'
GROUP BY EM.EMPLOYEE_ID, EM.LAST_NAME, EM.FIRST_NAME
) e
WHERE cnt >= 1.25 * avg_cnt

Related

Handle the case if an employee have more than one allowance

I have to write a simple query that calculates the total salary and I have a problem that if an employee have more than allowance it will show him twice.
This is what I wrote:
SELECT
employee.ename, Dept.Dname
, (Employee.Salary + ISNULL(allownces.amount,0)-ISNULL(deduction.amount,0)) AS total_salary
, allownces.amount AS allow, deduction.amount AS ded
FROM Employee
LEFT JOIN Dept ON Dept.id = Employee.dept_id
LEFT JOIN allownces ON allownces.emp_id = Employee.id
LEFT JOIN deduction ON deduction.emp_id = Employee.id
GROUP BY ename, Dname, Salary, allownces.amount, deduction.amount
and the result it will calculate the total salary of an employee if he have 2 allowance then it will calculate it two times and I want to calculate the allowance if he have more than one and show it as one.
Try with outer apply instead of left join.
SELECT
employee.ename, Dept.Dname, (Employee.Salary + ISNULL(a.amount,0)-ISNULL(d.amount,0)) AS total_salary
, allownces.amount AS allow, deduction.amount AS ded
FROM Employee
LEFT JOIN Dept ON Dept.id = Employee.dept_id
OUTER APPLY (
SELECT sum(amount) amount
FROM allownces
WHERE allownces.emp_id = Employee.id
) a
OUTER APPLY (
SELECT sum(amount) amount
FROM deduction
WHERE deduction.emp_id = Employee.id
) d

List the surnames of bosses who manage at least two employees from the query below

I need to get the surnames of bosses who manage at least two employees from the query below that earn no more than twice the average earnings of ALL people they direct.
I'm stuck here:
SELECT surname from emp k INNER JOIN
(SELECT surname, base_salary
from emp p LEFT JOIN
(select id_team, avg(base_salary) as s, count(*) as c from emp group by id_team)
as o ON(p.id_team = o.id_team)
where p.base_salary between o.s*0.7 and o.s*1.3 and o.c >=2) l ON (k.id_boss = o.id_boss)
having count(k.id_boss) >2 ??? AND k.base_salary < ????
I hope you get my point. Any advices how could I do that?
Here's what the full table looks like:
Based on your query you should just add the proper having clause
having count(k.id_boss) >2 AND k.base_salary < 2*l.s
SELECT k.surname
from emp k
INNER JOIN (
SELECT surname, base_salary, id_boss
from emp p
LEFT JOIN (
select id_team, avg(base_salary) as s, count(*) as c
from emp
group by id_team
) o ON p.id_team = o.id_team
where p.base_salary between o.s*0.7 and o.s*1.3 and o.c >=2
) l ON k.id_boss = o.id_boss
group by k.surname
having count(l.id_boss) >2
AND k.base_salary < 2*l.s

Get employees which have smaller salary than any of those who sold more than one order

Sorry for long title but I wanted to explain the situation.
My brains are almost exploding I have tried this for five hours now, and I don't get it. Got just a big headache.
I want to get those employees which haec smaller salary than anyone of those who has sold one or more orders. There is two tables EMPLOYEES and ORDERS.
EMPLOYEES have these columns; First name, Last name, Social security number, Salary.
ORDERS have these columns; Social security number, OrderID
This is best solution so far.
SELECT H.SOCSECNUM, H.LASTNAME, H.FIRSTNAME, H.SALARY
FROM EMPLOYEES H
WHERE H.SALARY < ALL(SELECT COUNT(T.ORDERID)
FROM ORDERS T
WHERE H.SOCSECNUM = T.SOCSECNUM
HAVING COUNT(T.ORDERID) > 0
);
I understand this like get social security number, name and salary of all employees which have smaller salary than anyone who sold more than 0 orders.
Am I stupid or what is wrong in that? Now this prints all employees which have 0 orders. If i change 0 -> 1 it prints all employees which have one or less orders.
I think that's the query you wanted to write:
select e.*
from employees e
where h.salary < all (
select h1.salary
from employees e1
where exists (select 1 from orders o1 where o1.socsecnum = e1.socsecnum)
)
The subquery returns the list of salaries of employees that performed at least one sale. You can then use all to filter the table against that.
You could also use aggregation:
select e.*
from employees e
where h.salary < (
select min(h1.salary)
from employees e1
where exists (select 1 from orders o1 where o1.socsecnum = e1.socsecnum)
)
You need the number of orders and salary for employees. This is helpful in one row. So, use JOIN:
select e.*, numorders
from employees e left join
(select o.socseqnum, count(*) as numorders
from orders o
group by o.socseqnum
) o
on e.socseqnum = o.socseqnum;
Then, I would use window functions to get the minimum salary for the one-order employees and use a comparison to that:
select eo.*
from (select e.*, o.numorders,
min(case when numorders = 1 then e.salary end) over () as min_salary_1order
from employees e left join
(select o.socseqnum, count(*) as numorders
from orders o
group by o.socseqnum
) o
on e.socseqnum = o.socseqnum
) eo
where salary < min_salary_1order
Using uncorrelated subquery
select *
from employees
where salary < (select min(salary)
from employees
where socsecnum in (select socsecnum
from orders
where socsecnum is not null));

How to find the AVG given some instructions SQL

I'm trying to create a query that returns me the Market.name and the average of the employees who worked for a particular Market, for example the average of the employees who worked for "IKEA" is 10% compared to all of the total employees among all of the markets.
Try this
select m.name as "Market Name",
avg(w.employee_id) as "Avg.NumberofEmployeesPerMarket"
from workson w
left join employee e on ( e.employee_id = w.employee_id )
left join market m on ( m.market_id = w.market_id )
group by m.name;
You need such a SQL statement with joins
select m.name market_name,
100*round(count(w.employee_id)::decimal/
(select count(employee_id) from employee ),2)
as "Avg Percent of Emp. Per Market"
from workson w
left join market m on ( m.market_id = w.market_id )
where m.name = 'IKEA'
group by m.name;
I don't know about your DBMS, I tried if it is Postgres, remove ::decimal if MySQL
Rextester Demo 1
Rextester Demo 2

How to show the total number of employees and participants, and participation percentage in all departments?

I have the following database design:
Employees Table: EmployeeID, Name, OrgCode
Departments Table: OrgCode, DepartName
CompleteSurvey Table: ID, ParticipantID
And I need to develop one query that will display a table that shows the total number of employees in all departments and the total number of participants who completed the survey in all departments.
I could be able to find the total number of employees in all department by the following query:
SELECT COUNT(DISTINCT dbo.Employees.EmployeeID) AS [Total Number of Employees]
FROM dbo.Departments INNER JOIN
dbo.Employees ON dbo.Departments.OrgCode = dbo.Employees.OrgCode CROSS JOIN
dbo.CompleteSurvey
Then, I could be able to find the total number of participants in all department by the following query:
SELECT COUNT(DISTINCT dbo.CompleteSurvey.ID) AS [Total Number of Participants]
FROM dbo.Departments INNER JOIN
dbo.Employees ON dbo.Departments.OrgCode = dbo.Employees.OrgCode INNER JOIN
dbo.CompleteSurvey ON dbo.Employees.EmployeeID = dbo.CompleteSurvey.RespondantID
But I should have a one query only.
For example, if Department A has 100 employee and the number of participants is 50 out of 100
and Department B has 80 employee and the number of participants is 30
The query should show the following:
the total number of employees in all departments = 180
the total number of participants in all departments = 80
the percent completion in all of them = 80/180 = 44%
So how to do that?
I don't know SQL Server, I hope an Oracle solution could help too:
select e.employees, c.respondents, (c.respondents / e.employees) * 100 percentage
from (select count(*) employees from employees) e,
(select count(*) respondents from complete_survey) c
You don't need to involve the Department table in these calculations:
SELECT
TotalEmployees = COUNT(*),
TotalParticipants = COUNT(s.ParticipantID),
ParticipationPercentage = COUNT(s.ParticipantID) * 100.0 / COUNT(*)
FROM dbo.Employee e
LEFT JOIN (SELECT DISTINCT ParticipantID FROM dbo.CompleteSurvey) s
ON e.EmployeeID = s.ParticipantID