I have an employee table:
I have a category table which joins userid and category id:
Category with value 1 is senior manager.
I want to find senior manager of each employee.Seniors Managers with category value of 1.
I need the output like this:
How can we achieve this in SQL Server 2008?
Any help appreciated.
Try:
WITH Emp_CTE AS (
Select ID,EmployeeName,Manager from employee
UNION ALL
SELECT ecte.ID,ecte.EmployeeName,c.Manager
FROM employee c
INNER JOIN Emp_CTE ecte ON ecte.Manager = c.ID
)
SELECT a.ID,a.EmployeeName,b.EmployeeName
FROM Emp_CTE a
left join employee b
on a.Manager = b.ID
left join category c
on a.Manager = c.UserID
where c.Category = '1'
As this query calls for a Self Join, this should work:
SELECT a.EMPLOYEENAME as Employee,
b.EMPLOYEENAME as Senior_Manager
FROM employee a
LEFT JOIN
employee b ON a.ID = b.Manager
LEFT JOIN
category c ON b.ID = c.UserID
WHERE c.Category = 1
Related
I have two tables in Oracle DB
Person (
id
)
Bill (
id,
date,
amount,
person_id
)
I need to get person and amount from last bill if exist.
I trying to do it this way
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id AND b.date = (SELECT MAX(date) FROM Bill WHERE person_id = 1)
WHERE p.id = 1;
But this query works only with INNER JOIN. In case of LEFT JOIN it throws ORA-01799 a column may not be outer-joined to a subquery
How can I get amoun from the last bill using left join?
Please try the below avoiding sub query to be outer joined
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN(select * from Bill where date =
(SELECT MAX(date) FROM Bill b1 WHERE person_id = 1)) b ON b.person_id = p.id
WHERE p.id = 1;
What you are looking for is a way to tell in bills, for each person, what is the latest record, and that one is the one to join with. One way is to use row_number:
select * from person p
left join (select b.*,
row_number() over (partition by person_id order by date desc) as seq_num
from bills b) b
on p.id = b.person_id
and seq_num = 1
You cannot have a subquery inside an ON statement.
Instead you need to convert your LEFT JOIN statement into a whole subquery.
Not tested but this should work.
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN (
SELECT id FROM Bill
WHERE person_id = p.id
AND date = (SELECT date FROM Bill WHERE person_id = 1)) b
WHERE p.id = 1;
I'm not quite sure why you would want to filter for the date though.
Simply filtering for the person_id should do the trick
you should join Person and Bill to the result for max date in bill related to person_id
select Person.id, bill.amount
from Person
left join bill on bill.person_id = person.id
left join (
select person_id, max(date) as max_date
from bill
group by person_id ) t on t.person_id = Person.id and b.date = t.max_date
Hey you can do like this
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id AND b.date = (SELECT max(date) FROM Bill WHERE person_id = 1)
WHERE p.id = 1
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id
WHERE (SELECT max(date) FROM bill AS sb WHERE sb.person_id=p.id LIMIT 1)=b.date;
SELECT
p.id,
c.amount
FROM Person p
LEFT JOIN (select b.person_id as personid,b.amount as amount from Bill b where b.date1= (select max(date1) from Bill where person_id=1)) c
ON c.personid = p.id
WHERE p.id = 1;
try this
select * from person p
left join (select MAX(id) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
from bills b) b
on p.id = b.person_id
I use GREATEST() function in join condition:
SELECT
p.id,
b.amount
FROM Person p
LEFT JOIN Bill b
ON b.person_id = p.id
AND b.date = GREATEST(b.date)
WHERE p.id = 1
This allows you to grab the whole row if necessary and grab the top x rows
SELECT p.id
,b.amount
FROM person p
LEFT JOIN
(
SELECT * FROM
(
SELECT date
,ROW_NUMBER() OVER (PARTITION BY person_id ORDER BY date DESC) AS row_num
FROM bill
)
WHERE row_num = 1
) b ON p.id = b.person_id
WHERE p.id = 1
;
I have four tables Student,Enrolment,Building,Campus and their fields are as:
Student:
StudentID
Name
Level
Enrolment:
Ref
StudentID
Course
EnrolDate
Building_ID
Building:
BuildingID
BuildingName
CampusID
Campus:
CampusID
CampusName
I need Name of students who are enrolled and studying at the CampusName = 'City Centre'. I tried numerous things but because it needs multiple connections to different tables I got really confused.
Thank you
Something like this:
SELECT S.Name
FROM Student S
INNER JOIN Enrolment E ON S.StudentID = E.StudentID
INNER JOIN Building B ON E.Building_ID = B.BuildingID
INNER JOIN Campus C ON C.CampusID = B.CampusID
WHERE C.CampusName = 'City Centre'
Just do the joins in order -- left to right:
SELECT *
FROM Student S
JOIN Enrolment E ON E.StudentID = S.StudentID
JOIN Building B ON B.BuildingID = E.Building_ID
JOIN Campus C ON C.CampusID = B.CampusID
WHERE C.CampusName = 'City Centre'
Try this:
SELECT S.*
FROM Students S INNER JOIN
Enrolment E ON E.StudentID=S.StudentID INNER JOIN
Building B ON B.BuildingID= E.Building_ID INNER JOIN
Campus C ON C.CampusID=E.CampusID
WHERE CampusName = 'City Centre'
I have a query with a not in clause like this:
select *
FROM COMPANY c
where c.company_id not In (SELECT SenderId
FROM CrossRef)
and c.id not in (select company_id
FROM USER)
I am wondering if there is a way to re-write that query using a left join in SQL Server 2008.
I tried the following one but it's not giving the correct result
select c.id, c.company_id
from COMPANY c
left join CrossRef cr on c.company_id != cr.senderid, COMPANY c1
left join USER u on c1.id != u.company_id
SELECT *
FROM Company C
LEFT JOIN CrossRef R ON R.SenderID = C.CompanyID
LEFT JOIN [User] U ON U.company_id = C.id
WHERE R.SenderID IS NULL
AND U.company_id IS NULL
How do i select all the employees of a company and its child companies?
Using SQL Server 2008
Employee
Id | Name | CompanyId
Company
Id | Name | ParentCompanyId
Example:
1 Microsoft 0
2 Microsoft India 1
3 Microsoft Spain 1
I have this below query which gives only employees from Microsoft and not from Microsoft India & Spain.
SELECT Id, Name FROM Employee WHERE CompanyId=1
I am not good in SQL. Help me on this.
Use a CTE to build the company hierarchy, then join this back to the Employees table:
with CompanyHierarchy as
(
select Id
from Company
where Id = 1
union all
select c.Id
from Company c
inner join CompanyHierarchy ch on c.ParentCompanyId = ch.Id
)
select e.*
from CompanyHierarchy ch
inner join Employees e on ch.Id = e.CompanyId
SQL Fiddle with demo.
You can also substitute a CompanyId variable into the anchor portion of the CTE if you want to parameterize the statement:
with CompanyHierarchy as
(
select Id
from Company
where Id = #CompanyId
union all
select c.Id
from Company c
inner join CompanyHierarchy ch on c.ParentCompanyId = ch.Id
)
select e.*
from CompanyHierarchy ch
inner join Employees e on ch.Id = e.CompanyId
SQL Fiddle with demo, now with added hierarchy levels.
SELECT
employee.name,
company.id
FROM employee
INNER JOIN company
On employee.companyId= company.id
WHERE company.id IN (1,2,3)
And it is correct for the query as you are asking only for the records whose company id is 1.
You have to write your query something like this.
SELECT Id, Name FROM Employee WHERE CompanyId in (SELECT Id FROM Company)
Now I have tried the above, which does what your given query is required to do. But for the desired results on the basis of Comapny/ParentCompany, please try the following query.
SELECT e.Id, e.Names FROM Employee e WHERE e.CompanyId = 1
or e.CompanyId in (SELECT c.Id FROM Company c where c.ParentCompanyId = 1)
Hope this helps.
I've always done this back asswards in PHP or ASAP, so I figure it's time to actually learn the proper way to do it in SQL. I have the following 4 tables in a database:
Category (Fields: CategoryNumber, Desc) (small table with 15 rows)
Media (Fields: MediaID, Desc, CategoryNumber, etc) (huge table with 15,000 rows)
Sales (Fields: Date, MediaID, EmployeeID etc) (huge table with 100,000 rows)
Employees (Fields: EmployeeID, Name, etc) (small table with only 20 rows)
Category only links to Media
Media has links to both Category and Sales.
Sales links to both the Media and Employee
Employee only links to Sales
What I would like to do is to write a query which tells me what categories a given employee has never sold any media in.
I can write a simple query that looks for unmatched data between 2 tables, but I have no clue how to do it when I'm dealing with 4 tables.
Thanks for your time and help!
Here's my suggestion:
select *
from Category c
where not exists (
select *
from Employee e
inner join Sales s on s.EmployeeId = e.EmployeeId
inner join Media m on m.MediaID = s.MediaID
where e.Name = 'Ryan' and m.CategoryNumber = c.CategoryNumber
)
To query all employes with the categories in which they didn't sell anything:
select e.EmployeeName, c.CategoryNumber
from Category c
cross join Employee e
where not exists (
select *
from Sales s
inner join Media m on m.MediaID = s.MediaID
where c.categoryNumber = m.CategoryNumber
and s.EmployeeId = e.EmployeeId
)
SELECT c.CategoryNumber, c.Desc
FROM Category c
WHERE NOT EXISTS
(
SELECT *
FROM Employees e
INNER JOIN Sales s on s.EmployeeID = e.EmployeeID
INNER JOIN Media m on m.MediaID = s.MediaID
WHERE e.Name = "Ryan"
AND m.CategoryNumber = c.CategoryNumber
)
MS Access evidently needs a lot of parentheses (thanks, Ryan!):
select *
from Category c
where not exists
( select *
from ( Employee e
inner join Sales s on (s.EmployeeId = e.EmployeeId))
inner join Media m on (m.MediaID = s.MediaID)
where (e.Name = 'Ryan' and m.CategoryNumber = c.CategoryNumber) )
select c.desc
from category
left outer join (select s.employeeid,m.categorynumber
from sales s
inner join media m on s.mediaid=m.mediaid
inner join employee e on e.employeeid=s.employeeid
where e.name = 'JOE'
group by employeeid,categorynumber) t on t.categorynumber=c.categorynumber
where s.employeeid is null
Modified Answer based on the solution provided by Carl in Access SQL Syntax:
select *
from Category c
where not exists (
select *
from (Employee e
inner join Sales s on (s.EmployeeId = e.EmployeeId))
inner join Media m on (m.MediaID = s.MediaID)
where (e.Name = 'Ryan' and m.CategoryNumber = c.CategoryNumber)
)