1. 程式人生 > >sql查詢每組前幾條記錄

sql查詢每組前幾條記錄

首先建立測試資料

CREATE TABLE `t2` (
  `id` int(11) NOT NULL,
  `gid` char(1) DEFAULT NULL,
  `col1` int(11) DEFAULT NULL,
  `col2` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `t2` VALUES ('1', 'A', '31', '6');
INSERT INTO `t2` VALUES ('2', 'B', '25', '83');
INSERT INTO `t2` VALUES ('3', 'C', '76', '21');
INSERT INTO `t2` VALUES ('4', 'D', '63', '56');
INSERT INTO `t2` VALUES ('5', 'E', '3', '17');
INSERT INTO `t2` VALUES ('6', 'A', '29', '97');
INSERT INTO `t2` VALUES ('7', 'B', '88', '63');
INSERT INTO `t2` VALUES ('8', 'C', '16', '22');
INSERT INTO `t2` VALUES ('9', 'D', '25', '43');
INSERT INTO `t2` VALUES ('10', 'E', '45', '28');
INSERT INTO `t2` VALUES ('11', 'A', '2', '78');
INSERT INTO `t2` VALUES ('12', 'B', '30', '79');
INSERT INTO `t2` VALUES ('13', 'C', '96', '73');
INSERT INTO `t2` VALUES ('14', 'D', '37', '40');
INSERT INTO `t2` VALUES ('15', 'E', '14', '86');
INSERT INTO `t2` VALUES ('16', 'A', '32', '67');
INSERT INTO `t2` VALUES ('17', 'B', '84', '38');
INSERT INTO `t2` VALUES ('18', 'C', '27', '9');
INSERT INTO `t2` VALUES ('19', 'D', '31', '21');
INSERT INTO `t2` VALUES ('20', 'E', '80', '63');
INSERT INTO `t2` VALUES ('21', 'A', '89', '9');
INSERT INTO `t2` VALUES ('22', 'B', '15', '90');
INSERT INTO `t2` VALUES ('23', 'C', '46', '84');
INSERT INTO `t2` VALUES ('24', 'D', '54', '79');
INSERT INTO `t2` VALUES ('25', 'E', '85', '64');
INSERT INTO `t2` VALUES ('26', 'A', '87', '13');
INSERT INTO `t2` VALUES ('27', 'B', '40', '90');
INSERT INTO `t2` VALUES ('28', 'C', '34', '90');
INSERT INTO `t2` VALUES ('29', 'D', '63', '8');
INSERT INTO `t2` VALUES ('30', 'E', '66', '40');
INSERT INTO `t2` VALUES ('31', 'A', '83', '49');
INSERT INTO `t2` VALUES ('32', 'B', '4', '90');
INSERT INTO `t2` VALUES ('33', 'C', '81', '7');
INSERT INTO `t2` VALUES ('34', 'D', '11', '12');
INSERT INTO `t2` VALUES ('35', 'E', '85', '10');
INSERT INTO `t2` VALUES ('36', 'A', '39', '75');
INSERT INTO `t2` VALUES ('37', 'B', '22', '90');
INSERT INTO `t2` VALUES ('38', 'C', '76', '67');
INSERT INTO `t2` VALUES ('39', 'D', '20', '11');
INSERT INTO `t2` VALUES ('40', 'E', '81', '36');

網上大多數例子都是用類似如下寫法,其實是錯誤的:

select d.Name as Department, e.Name as Employee, e.Salary as Salary
    from Employee as e inner join Department as d
    on e.DepartmentId = d.Id
    where (select count(distinct(e1.Salary)) from Employee as e1 where e1.DepartmentId = e.DepartmentId and e1.Salary > e.Salary) < 3
    order by e.Salary desc;

這個sql的原理是根據排序欄位,逐個分數比較,取總數小於要取的排名數,當排序欄位可以重複時,排序欄位前一個出現重複時會導致該分組無記錄或是少記錄

oracle或MySQL(版本在8.0以上)在mysql(8.0.12)上測試通過:

SELECT
	*
FROM
	(
		SELECT
			s.*, row_number() over (
				PARTITION BY gid
				ORDER BY
					col2 DESC
			) AS class_rank
		FROM
			t2 s
	) d
WHERE
	d.class_rank <= 2
order by gid,col2 desc

mysql低版本,使用變數的方式(已測試):


select * from 
(
select  
     @rows:=CASE when @ids=a.gid then  @rows+1 else 1 end as groupRow,
     @ids:=a.gid as gid,
     a.col2  

  from  t2 a ,( select @rows:=1, @ids:='') b
 ORDER BY   a.gid , a.col2  desc
) w
where w.groupRow <=2

如有問題麻煩提出來共同解決~