65.9K
CodeProject is changing. Read more.
Home

Selecting parent records with specific subset of child records

Nov 15, 2011

CPOL

2 min read

viewsIcon

30060

I will show you how you can select one parent row with two latest child rows using T-SQL

Introduction Imagine this kind of SQL query - you have a parent/child tables such as Product/ProductItem, Company/Employee, Article/Categories where parent and child tables are connected with one-to-many relationship. Let we assume that you have following Company/Employee tables with the following structure: Company +CompanyId +CompanyName Employee +EmployeeId +CompanyId +EmployeeName +DateHired +Salary Each company can have several employees which are connected via CompanyId foreign key. Also, date when employee is hired is placed in the Employee table Problem How can you create SQL query that returns parent row and exactly two child rows? examples of such kind of queries are: 1. List all companies and employee who has been hired first 2. List all companies and last two hired employees 3. List all companies with two employees with the highest salaries Example of result for the query number 2 would be: Companies | Date Hired | Employee ----------------------------------------- Company1 | 17/11/2011 | John Spenser Company1 | 16/11/2011 | Mike Johnson Company2 | 10/11/2011 | Jasmin Fleet Company2 | 05/11/2011 | George Lee Company3 | 14/11/2011 | John Do Company3 | 13/11/2011 | Adam Johnson Company4 | 06/11/2011 | Adelle Spenser Company4 | 28/10/2011 | Stephen Murphy Solution You will need to join Company and Employee tables and partition the results by CompanyId, in order to group results by companies. Then, you will need order employees by date hired (or salary - this is specific for your problem) and find order index with this condition. In the final query you will filter results by order index (e.g. if you need last two employees you will put order_index < 2 in the WHERE clause) In the following listing is shown that kind of code:
WITH company_employees (CompanyName, EmployeeName, DateHired, order_index) AS (
	
SELECT	Company.CompanyName,
	Employee.EmployeeName, 
	Employee.DateHired, 
	ROW_NUMBER() OVER( PARTITION BY Company.CompanyId
				ORDER BY Employee.DateHired desc)
	FROM         Company
	INNER JOIN   Employee
		ON Employee.CompanyId = Company.CompanyId
)
SELECT * FROM company_employees
WHERE order_index IN ( 1,2)
In this query I have user common table expression (neater replacement for sub-query) where I have joined parent and child table. ROW_NUMBER function returns me index of the employee partitioned by companies ordered in the by the date hired i descending order) In the main query I have filtered only those records that have order_index 1 or 2 because I need to find only last two hired employees in each company. If I have placed ascending order in the ROW_NUMBER, two employees that are hired first would be returned. instead of the DateHired I could use any other field such as salary. With minor change you can also use this query if you have similar requirement.