之前在開發的時候遇到過一個需求,就是要按照某一列進行分組後取前幾條數據,今天又有同事碰到了,幫解決了以後順便寫一篇博客記錄一下。數據庫
首先先建一個基礎數據表,代碼以下:函數
IF OBJECT_ID(N'Test') IS NOT NULL
BEGIN
DROP TABLE Test
END3dCREATE TABLE Test(
ID bigint IDENTITY(1,1),
Name nvarchar(50),
Department nvarchar(50))
blogINSERT INTO Test(Name,Department)
VALUES('張三','行政'),
('李四','運營'),
('王五','行政'),
('趙六','研發'),
('錢七','工程'),
('Amy','研發'),
('Tomy','工程'),
('Tony','研發'),
('Tom','工程'),
('Alice','行政'),
('Mary','行政'),
('Elaine','運營'),
('Geno','行政'),
('Gary','工程')
GO排序
建好後,這張表的數據以下:開發
如今的需求是按照Department列進行分組,按ID取每一個部門前2條記錄,只寫一條SQL語句的話,分別能夠用3種方法實現,代碼以下:get
SELECT ID,Name,Department FROM
(SELECT nn=ROW_NUMBER() OVER(PARTITION BY Department ORDER BY ID),* FROM Test) b WHERE nn<=2博客
SELECT * FROM Test t WHERE
(SELECT COUNT(*) FROM Test WHERE Department=t.Department AND ID<=t.ID)<=2 ORDER BY Departmentit
SELECT * FROM Test t
WHERE ID in (SELECT DISTINCT TOP 2 ID FROM Test WHERE Department=t.Department)
ORDER BY Department基礎
第一種方法使用了ROW_NUMBER()函數,這個函數是在SQL 2005及以上版本纔有的,因此若是數據庫是2000的話只能用下面兩種方法,運行以後獲得的結果都同樣,以下圖:
總結,碰到此類需求能夠直接用下面代碼進行套用:
SELECT 要輸出的列,除nn外 FROM
(SELECT nn=ROW_NUMBER() OVER(PARTITION BY 分組的列 ORDER BY 排序的列),* FROM 表名) b WHERE nn<=前N條數據
SELECT * FROM 表名 t WHERE
(SELECT COUNT(*) FROM 表名 WHERE 分組的列=t.分組的列 AND 排序的列<=t.排序的列)<=前N條數據 ORDER BY 分組的列
SELECT * FROM 表名 t
WHERE 排序的列 in (SELECT DISTINCT TOP 前N條數據 排序的列 FROM 表名 WHERE 分組的列=t.分組的列)
ORDER BY 分組的列