Top N Random records from each group
Problem:
The requirement is to get top 10 employee’s name randomly from each department in a company. Let me elaborate it. Suppose in a company ABC, there are 1500 employees with 5 departments and each department have more than 200 employees. The manager wants to list down at least 10 names of the employees randomly from each department for a survey.
Solution:
In a given [Employees] table with columns [EmployeeName], [DeptName] we have some data, let’s say around 1500 records.
Use the below script to create and populate data in the [Employee] table:
CREATE TABLE [dbo].[Employees]( [EmployeeName] [VARCHAR](50) NULL, [DeptName] [VARCHAR](50) NULL ) ON [PRIMARY]
To populate [Employees] table with dummy data:
DECLARE @emptemp TABLE ( [EmployeeName] VARCHAR(50) ,[DeptName] VARCHAR(50) ) DECLARE @dept INT DECLARE @employee INT SET @dept = 65 SET @employee = 70 WHILE @dept < 70 BEGIN WHILE @employee < 90 BEGIN INSERT INTO @emptemp ([EmployeeName] ,[DeptName]) VALUES( CHAR(@employee), CHAR(@dept) + CHAR(@dept + 1) ) SET @employee = @employee + 1 END SET @employee = 70 SET @dept = @dept + 1 END INSERT INTO [dbo].[Employees] ([EmployeeName] ,[DeptName]) SELECT [EmployeeName] ,[DeptName] FROM @emptemp SELECT * FROM dbo.Employees
Below are the different ways to get the problem solved:
- By Using Cursor
/* The below script will show random 10 records from each department from Employees table. */ DECLARE @deptColumn VARCHAR(50) --For creation of a temporary table with no data. SELECT * INTO #temporaryT FROM dbo.Employees WHERE 1=2 DECLARE UserCursor CURSOR FOR SELECT DISTINCT DeptName FROM dbo.Employees OPEN UserCursor FETCH NEXT FROM UserCursor INTO @deptColumn WHILE @@FETCH_STATUS = 0 BEGIN INSERT INTO #temporaryT SELECT TOP 10 * FROM dbo.Employees WHERE DeptName = @deptColumn ORDER BY NEWID() --newid() for random records FETCH NEXT FROM UserCursor INTO @deptColumn END CLOSE UserCursor DEALLOCATE UserCursor SELECT * FROM #temporaryT ORDER BY DeptName DROP TABLE #temporaryT
- By Using ROW_NUMBER: Here is the short and effective query to do the above operation.
SELECT DeptName,EmployeeName FROM (SELECT ROW_NUMBER() OVER(PARTITION BY DeptName ORDER BY newid() ) AS RowID , * FROM dbo.Employees ) InnerQ WHERE InnerQ.RowID <= 10 --RANK() can also be used instead of ROW_NUMBER()
- By using WITH : another descent code to get the above result set
WITH distinctDepts AS (SELECT DISTINCT DeptName FROM dbo.Employees) SELECT InnerQ.* FROM distinctDepts d CROSS APPLY (SELECT TOP 10 * FROM dbo.Employees WHERE DeptName = d.DeptName ORDER BY newid()) InnerQ
Hope these queries will be helpful in pulling down your stress level.

This is very helpful.
I wonder if there is a script to generate random valid names? i would be needing this for testing purposes rather than manual data entry. I appreciate your help in this regard. Thanks!
Hi Arun
good to see ur website.
Its wonderful and it shows ur talent.
lalit
UCE-1999 passout
Electrical