SELECT P.FirstName, d.Name, EDH.StartDate
FROM HumanResources.EmployeeDepartmentHistory edh INNER JOIN HumanResources.Department d
ON EDH.DepartmentID=D.DepartmentID
INNER JOIN HumanResources.Employee e
ON EDH.BusinessEntityID=E.BusinessEntityID
INNER JOIN Person.Person P
ON E.BusinessEntityID=P.BusinessEntityID
WHERE EndDate IS NULL
ORDER BY D.NAME;
I am trying to list the person in each department that has worked there the longest. I know that using the top(1) for each department would most likely be the best option but I can figure if using partition or group by is going to be the better option in this case. Anybody with more skill than me have any ideas?
Working the longest means the earliest start date. That suggests:
SELECT ed.*
FROM (SELECT P.FirstName, d.Name, EDH.StartDate,
RANK() OVER (PARTITION BY D.DepartmentID ORDER BY EDH.StartDate) as seqnum
FROM HumanResources.EmployeeDepartmentHistory edh JOIN
HumanResources.Department d
ON EDH.DepartmentID = D.DepartmentID JOIN
HumanResources.Employee e
ON EDH.BusinessEntityID = E.BusinessEntityID JOIN
Person.Person P
ON E.BusinessEntityID = P.BusinessEntityID
WHERE EndDate IS NULL
) ed
WHERE seqnum = 1
ORDER BY D.NAME;
Related
I have below three SQL statement and I want to select out like below, I tried but not success.
Need some
help.
Output:
member_id, balance, firstname, lastname, LastPurchase, LastOrde
SELECT c.member_id
, c.firstname
, c.lastname
, m.balance
FROM member m
, customer c
where m.member_id = c.member_id
order
by m.member_id
SELECT member_id, max(date) as LastPurchase
FROM purchase
GROUP
BY member_id
SELECT member_id, max(date) as LastOrder
FROM ordert
GROUP
BY member_id
You can join these statements -
SELECT c.member_id, c.firstname, c.lastname, m.balance, p.LastPurchase, o.LastOrder
FROM member m
join customer c on m.member_id = c.member_id
left join (SELECT member_id, max(date) as LastPurchase
FROM purchase
GROUP BY member_id) p on p.member_id = m.member_id
left join (SELECT member_id, max(date) as LastOrder
FROM ordert
GROUP BY member_id) o on o.member_id = m.member_id
order by m.member_id
You can join the aggregate queries. The JOIN ... USING syntax comes handy here, since all join column names are the same:
SELECT c.member_id, c.firstname, c.lastname, m.balance, p.last_purchase, o.last_purchase
FROM member m
INNER JOIN customer c USING(member_id)
INNER JOIN (
SELECT member_id, max(date) last_purchase FROM purchase GROUP BY member_id
) p USING(member_id)
INNER JOIN (
SELECT member_id, max(date) last_order FROM order GROUP BY member_id
) o USING(member_id)
ORDER BY c.member_id
Important: your original query uses implicit, old-shool joins (with a comma in the from clause) - this syntax fell out of favor more than 20 years ago and its use is discourage, since it is harder to write, read, and understand.
One of the many benefits of using explicit joins here is that you can easily change the INNER JOINs to LEFT JOINs if there is a possibility that a member has no purchase or no order at all.
I need to write a query to find the youngest customer who bought atleast 1 product
Here is the data:
CUSTOMER:
ORDER_DETAIL:
This is my query so far:
SELECT c.CUSTOMERID, c.age, c.name
from (
SELECT CUSTOMERID, COUNT(ORDERID) as "totalOrder"
FROM FACEBOOK_ORDER_DETAIL
GROUP BY CUSTOMERID
HAVING COUNT(ORDERID) >=1) AS tbl
LEFT JOIN FACEBOOK_CUSTOMER c on c.CUSTOMERID = tbl.CUSTOMERID
order by c.age ;
However, above query gives me
But I need the list of customers with the minimum age.
If you really only want a single youngest customer, even should there be a tie, then use LIMIT:
SELECT c.CUSTOMERID, c.age, c.name
FROM CUSTOMER c
INNER JOIN FACEBOOK_ORDER_DETAIL o
ON c.CUSTOMERID = c.CUSTOMERID
ORDER BY
c.age
LIMIT 1;
This should work because if a customer joins to the order details table, it implies that he had at least one order.
If instead you want to find all youngest customers, including all ties, then a nice way to handle this uses the RANK analytic function:
SELECT DISTINCT CUSTOMERID, age, name
FROM
(
SELECT c.CUSTOMERID, c.age, c.name, RANK() OVER (ORDER BY c.age) rnk
FROM CUSTOMER c
INNER JOIN FACEBOOK_ORDER_DETAIL o
ON c.CUSTOMERID = o.CUSTOMERID
) t
WHERE rnk = 1;
Demo
For earlier versions of MySQL, we can use a subquery as a workaround for not having RANK:
SELECT DISTINCT c.CUSTOMERID, c.age, c.name
FROM CUSTOMER c
INNER JOIN FACEBOOK_ORDER_DETAIL o
ON c.CUSTOMERID = c.CUSTOMERID
WHERE c.age = (SELECT MIN(t1.age)
FROM CUSTOMER t1
INNER JOIN FACEBOOK_ORDER_DETAIL t2
ON t1.CUSTOMERID = t2.CUSTOMERID);
Demo
You only want columns from customers, so I would phrase this as:
select c.*
from (select c.*,
rank() over (order by age) as seqnum
from customers c
where exists (select 1
from facebook_order_detail fod
where fod.customerid = c.customerid
)
) c
where seqnum = 1;
In particular, this requires no duplicate elimination or aggregation, so it should be faster. And it can use an index on face_book_details(customerid) and also perhaps on customers(age, customerid).
I have this query
SELECT t.pname,MAX(t.name) ,MAX(t.total)
FROM
(
SELECT p.`id`,e.`name`,p.`pname`,(m.`hour`) AS total
FROM employee e INNER JOIN epmap m ON m.`employeeID`=e.`id` INNER JOIN project p ON p.`id`=m.`projectID`
)t
GROUP BY t.id
it gives the right answer, but its not the good approach beacuse Max(t.name) not appropriate
This will give you the result you need:
SELECT t.pname, t.name, t.hour as total
FROM (
SELECT p.id, e.name, p.pname, m.total,
ROW_NUMBER() OVER(partition by p.id order by m.hour desc) rn
FROM employee e
INNER JOIN epmap m ON m.employeeID=e.id
INNER JOIN project p ON p.id=m.projectID
) t
where t.rn = 1
SELECT DISTINCT would probably let you get rid of the MAX on name.
Please don't bite me for this, but I'm new to mysql and I have some problem with using pseudonym in WHERE clause. I thought that it is possible to use pseudonym for aggregate function, defined in the select statement.
Here is my query
SELECT a.name, s.name, COUNT(e.id) as total FROM athletes a
INNER JOIN sports s on s.id = a.sport_id
INNER JOIN events e on s.id = e.sport_id
WHERE total >=2 GROUP BY a.name
But, I catch an error "Unknown column total in WHERE clause".
Could anyone tell me if it is right to do query like this?
You can not use alias in the where clause. You need to use that in having
SELECT
a.name,
s.name,
COUNT(e.id) as total FROM athletes a
INNER JOIN sports s on s.id = a.sport_id
INNER JOIN events e on s.id = e.sport_id
GROUP BY a.name having total >=2
Instead of WHERE total >=2 you can use HAVING (total >= 2 )
HAVING:
SELECT a.name, s.name, COUNT(e.id) as total
FROM athletes a
INNER JOIN sports s on s.id = a.sport_id
INNER JOIN events e on s.id = e.sport_id
GROUP BY a.name, s.name
HAVING (total >= 2 );
Yo can not use an column alias in where clause. you have to use the expression COUNT(e.id) in where clasue or you can use the alias in a having clause:
SELECT a.name, s.name, COUNT(e.id) as total FROM athletes a INNER JOIN sports s on s.id = a.sport_id INNER JOIN events e on s.id = e.sport_id WHERE COUNT(e.id)>=2 GROUP BY a.name
or
SELECT a.name, s.name, COUNT(e.id) as total FROM athletes a INNER JOIN sports s on s.id = a.sport_id INNER JOIN events e on s.id = e.sport_id having total>=2 GROUP BY a.name
I have an employee table and a leave_allocation table which has a one-to-many relationship, Each employee has a number of leave allocations over a period of time. I would like to get the LATEST allocation for each employee.
I tried the query but the date and the days values do not correlate to the same row
select e.employee_number, e.nme, MAX(l.date), l.days
from employee e, leave_allocation l
where l.employee_id = e.employee_id
group by e.employee_number, e.nme
How can I get the latest allocation per employee?
SELECT e.employee_number
,e.nme
,l.days
FROM employee e
, leave_allocation l
,(SELECT employee_id
,MAX(DATE) date
FROM leave_allocation
GROUP BY employee_id) m
WHERE l.employee_id = e.employee_id
AND l.employee_id = m.employee_id
AND l.date = m.date
If there can be multiple rows with same employee_number and date, then you need to sum.
SELECT e.employee_number
,e.nme
,sum(l.days)
FROM employee e
, leave_allocation l
,(SELECT employee_id
,MAX(DATE) date
FROM leave_allocation
GROUP BY employee_id) m
WHERE l.employee_id = e.employee_id
AND l.employee_id = m.employee_id
AND l.date = m.date
GROUP BY e.employee_number
,e.nme
Place the MAX() date in a subquery:
SELECT e.employee_number, e.nme, l.leavedate, la.days
FROM employee e
INNER JOIN
(
SELECT Max(date) leavedate, employee_id
FROM leave_allocation
GROUP BY employee_id
) l
ON e.employee_id = l.employee_id
INNER JOIN leave_allocation la
ON l.employee_id = la.employee_id
AND l.leavedate = la.date
I also switched the query to use ANSI join syntax instead of commas between the tables.
Try this one,
SELECT e.employee_number, e.nme, c.maxDate, l.days
FROM employee e
INNER JOIN leave_allocation l
ON l.employee_id = e.employee_id
INNER JOIN
(
select employee_id, MAX(date) maxDate
from leave_allocation
group by employee_id
) c ON c.employee_id = l.employee_ID AND
c.maxDate = l.date