In mySql I have 3 table name emp, emp_cat and emp_cat_relation. Employee Id from emp table and employee category id from emp_cat relate in emp_cat_relation table.
How I can pick last joined employee (1 or 2 row as I want) name and join date from each category using single sql query.
Date field in emp table
Use the LIMIT & ORDER BY Functions
SELECT *
FROM emp e
INNER JOIN emp_cat_relation ecr ON e.employee_id = ecr.employee_id
INNER JOIN emp_cat ec ON ecr.employee_category_id = ec..employee_category_id
ORDER BY e.date
LIMIT 2;
Related
I have 2 tables that I would like join where the contactid is unique and has the highest allowance.
EMPLOYEE
Employee ID
contactid
employerid
1
555444333
25435566
2
555444333
84235621
3
234232144
57353457
EMPLOYEEDETAILS
Employee ID
Annual Allowance
1
£10000
2
£1000
3
£2000
I would like to achieve below where I want to show the EmployeeID with the highest allowance for the unique contactid.
EmployeeID
contactid
Annual Allowance
1
555444333
£10000
3
234232144
£2000
I have tried the SQL code below but it's not giving me the unique contactid with the highest allowance.
SELECT EMPLOYEE.employeeid, EMPLOYEE.contactid, MAX(EMPLOYEEDETAILS.annualallowance)
from
cxm_employee EMPLOYEE
JOIN
cxm_employeedetails EMPLOYEEDETAILS ON EMPLOYEE.employeeid = EMPLOYEEDETAILS.employeeid
group by EMPLOYEE.employeeid,EMPLOYEE.employeecontactid
Where am I going wrong?
I want to show the EmployeeID with the highest allowance for the unique contactid.
Your code does not work because it only brings the details of the current employee, letting along other employees that have the same contactid.
I think it is easier to do with window functions:
select *
from (
select e.*, d.annualallowance,
rank() over(partition by e.contactid order by d.annualallowance desc) rn
from employee e
inner join employeedetails d on d.employeeid = e.employeeid
) t
where rn = 1
rank() ranks employees having the same contact by descending annual allowance ; we can then use this information for filtering.
In pre-8.0 versions of MySQL, where window functions are not supported, an alternative uses a correlated subquery to retrieve the top allowance per contact; we can then use this information to filter the dataset :
select e.*, d.annualallowance
from employee e
inner join employeedetails d on d.employeeid = e.employeeid
where d.annualallowance = (
select max(d1.annualallowance)
from employee e1
inner join employeedetails d1 on d1.employeeid = e1.employeeid
where e1.contactid = e.contactid
)
Demo on DB Fiddle
"employee" Table
emp_id
empName
1
ABC
2
xyx
"client" Table:
id
emp_id
clientName
1
1
a
2
1
b
3
1
c
4
2
d
"collection" Table
id
emp_id
Amount
1
2
1000
2
1
2000
3
1
1000
4
1
1200
I want to aggregate values from the three tables input tables here reported as samples. For each employee I need to find
the total collection amount for that employee (as a sum)
the clients that are involved with the corresponding employee (as a comma-separated value)
Here follows my current query.
MyQuery:
SELECT emp_id,
empName,
GROUP_CONCAT(client.clientName ORDER BY client.id SEPARATOR '') AS clientName,
SUM(collection.Amount)
FROM employee
LEFT JOIN client
ON clent.emp_id = employee.emp_id
LEFT JOIN collection
ON collection.emp_id = employee.emp_id
GROUP BY employee.emp_id;
The problem of this query is that I'm getting wrong values of sums and clients when an employee is associated to multiple of them.
Current Output:
emp_id
empName
clientName
TotalCollection
1
ABC
a,b,c,c,b,a,a,b,c
8400
2
xyz
d,d
1000
Expected Output:
emp_id
empName
clientName
TotalCollection
1
ABC
a , b , c
4200
2
xyz
d
1000
How can I solve this problem?
There are some typos in your query:
the separator inside the GROUP_CONCAT function should be a comma instead of a space, given your current output, though comma is default value, so you can really omit that clause.
each alias in your select requires the table where it comes from, as long as those field names are used in more than one tables among the ones you're joining on
your GROUP BY clause should at least contain every field that is not aggregated inside the SELECT clause in order to have a potentially correct output.
The overall conceptual problem in your query is that the join combines every row of the "employee" table with every row of the "client" table (resulting in multiple rows and higher sum of amounts during the aggregation). One way for getting out of the rabbit hole is a first aggregation on the "client" table (to have one row for each "emp_id" value), then join back with the other tables.
SELECT emp.emp_id,
emp.empName,
cl.clientName,
SUM(coll.Amount)
FROM employee emp
LEFT JOIN (SELECT emp_id,
GROUP_CONCAT(client.clientName
ORDER BY client.id) AS clientName
FROM client
GROUP BY emp_id) cl
ON cl.emp_id = emp.emp_id
LEFT JOIN (SELECT emp_id, Amount FROM collection) coll
ON coll.emp_id = emp.emp_id
GROUP BY emp.emp_id,
emp.empName,
cl.clientName
Check the demo here.
Regardless of my comment, here is a query for your desired output:
SELECT
a.emp_id,
a.empName,
a.clientName,
SUM(col.Amount) AS totalCollection
FROM (SELECT e.emp_id,
e.`empName`,
GROUP_CONCAT(DISTINCT c.clientName ORDER BY c.id ) AS clientName
FROM employee e
LEFT JOIN `client` c
ON c.emp_id = e.emp_id
GROUP BY e.`emp_id`) a
LEFT JOIN collection col
ON col.emp_id = a.emp_id
GROUP BY col.emp_id;
When having multiple joins, you should be careful about the relations and the number of results(rows) that your query generates. You might as well have multiple records in output than your desired ones.
Hope this helps
SELECT emp_id,
empName,
GROUP_CONCAT(client.clientName ORDER BY client.id SEPARATOR '') AS clientName,
C .Amount
FROM employee
LEFT JOIN client
ON clent.emp_id = employee.emp_id
LEFT JOIN (select collection.emp_id , sum(collection.Amount ) as Amount from collection group by collection.emp_id) C
ON C.emp_id = employee.emp_id
GROUP BY employee.emp_id;
it works for me now
I have a couple tables in MySQL DB
EID Name
1 Title A
2 Title B
3 Title C
LID EID Location Address Order
1 1 Office NY 1
2 1 Home IL 2
3 2 Office CA 1
4 3 Home NJ 2
I have the above 2 tables (Employee and Location). I would like to know the location of each Employee with office as a preferred choice and if 'office' does not exist then would need 'Home' location . The order column defined the order/priority of what is needed.
here is the output needed
EID LID Name Location Address
1 1 Title A Office NY
2 3 Title B Office CA
3 4 Title C Home NJ
The first join of the query below just connects the Employee and Location tables, but note that it results in all records from Location being joined. The critical part of the below query is the second INNER JOIN to a subquery. This subquery identifies the minimum (i.e. highest priority) order for each employee ID. This is then used to discard records from the first join which are not the highest priority.
SELECT t1.EID,
t2.LID,
t1.Name,
t2.Location,
t2.Address
FROM Employee t1
INNER JOIN Location t2
ON t1.EID = t2.EID
INNER JOIN
(
SELECT EID, MIN(`Order`) AS min_order
FROM Location
GROUP BY EID
) t3
ON t2.EID = t3.EID AND
t2.Order = t3.min_order
One other note: Don't name your columns Order, which is a MySQL keyword. To get my query to work, I had to put it in backticks, which is inconvenient to say the least, and possibly error prone.
Demo here:
SQLFiddle
There are two posibility to get your result.
1)If you need Based on Order result then use this query
SELECT e1.EID, l1.LID, e1.Name, l1.Location, l1.Address
FROM Employee e1
JOIN
(SELECT MIN(`Order `) as Minorder, EID, LID, Location, Address, Order
FROM Location l1
GROUP BY EID) l1
ON l1.EID = e1.EID AND l1.Minorder = l1.Order;
2)if you need result Based on EID then use this query
SELECT e1.EID,l1.LID,e1.Name,l1.Location,l1.Address
FROM Employee e1 JOIN
(SELECT MIN(`EID`)as Mineid,EID,LID,Location,Address,`Order` FROM Location l1 GROUP BY EID)l1
ON l1.Mineid = e1.EID;
Extra Note:-
Plese donot use mysql inbuilt keyword as Column name or Table name for more information read this link click here
You can the expected result by using inner join
Select a.eid,b.Lid,a.name,b.location,b.address from Table1 a innner join (select * from Tableb group by eid) b on
a.eid=b.eid;
you can try this code this will help you as i think
select E.EID,E.name,ad.LID,ad.LOCATION,ad.ADDRESS,ad.[order]
from #emp E inner join #address ad on E.EID = ad.EID
inner join (select EID, min([order]) [order]
from #address
group by EID) tt on ad.EID = tt.EIDand ad.[order] = tt.[order]
I have table employee which contains about 9 columns . ' id,name,etc..'
and I have another table 'onCall' contain 3 columns 'employee_id,department_id and rank '
what I want is to retrieve the employee data who is registered as OnCall employee on this department
I try this to get the employee data :
Select * from employee where id in (SELECT employee_id FROM onCall where department_id = 3)
But like this I can't know what is the rank of the onCall employee , is he registered as primary or backup ,how can I merge rank column from onCall table but only for the selected employee by the id
I tried to join them but I get syntax error
any way to solve this ?
This calls for an inner join
select EMP.*, OC.*
from EMPLOYEE EMP
inner join ONCALL OC
on OC.EMPLOYEE_ID = EMP.ID
where OC.DEPARTMENT = 3
This may help you and use the required columns with table alias name
Select e.*, o.* from employee e
LEFT JOIN onCall o ON o.employee_id = e.id
AND o.department_id = 3
Suppose that we have following tables:
company company_has_employee employee
-------------------------------------------------------------
id company_id id
companzy_name employee_id emplyee_name
How to create SQL Query, which retrieves any two employees, who works for the same company and what is this company?
Assuming juergen d's joins of the table are correct, I will modify the query to
select top 2 company_name, e.employee_name
from compyny c
join company_has_employee ce on ce.company_id = c.id
join employee e on e.id = cs.employee_id
group by company_name
having count(e.id) > 1
This will always return the top 2 employees
juergen d's original query will always return the first and last employees based on their ID.
If you want two employees chosen randomly, then you can try this:
select top 2 company_name, e.employee_name
from compyny c
join company_has_employee ce on ce.company_id = c.id
join employee e on e.id = cs.employee_id
group by company_name
having count(e.id) > 1
order by RAND((e.ID)*DATEPART(millisecond, GETDATE()))
The last order by clause will change the order of records randomly and you will always get the top 2 of a random order...which means 2 random employees will be selected each time the query is run.
select company_name,
min(e.employee_name) as emp1,
max(e.employee_name) as emp2
from compyny c
join company_has_employee ce on ce.company_id = c.id
join employee e on e.id = cs.employee_id
group by company_name
having count(e.id) > 1