mysql和oracle取Group By 第一条

Oracle 取Group By 第一条

在 Oracle 中,当你使用GROUP BY进行分组查询时,如果需要获取每组的第一条记录,可以使用以下几种常见的方法,下面将分别详细介绍。

方法一:使用ROW_NUMBER()窗口函数

ROW_NUMBER()是一个窗口函数,它可以为结果集中的每一行分配一个唯一的行号,你可以根据分组字段和排序字段来为每组内的记录编号,然后筛选出每组行号为 1 的记录。

示例表结构和数据

sql

复制代码
-- 创建示例表
CREATE TABLE employees (
    dept_id NUMBER,
    emp_id NUMBER,
    emp_name VARCHAR2(100),
    salary NUMBER
);

-- 插入示例数据
INSERT INTO employees VALUES (1, 101, 'Alice', 5000);
INSERT INTO employees VALUES (1, 102, 'Bob', 6000);
INSERT INTO employees VALUES (2, 103, 'Charlie', 4500);
INSERT INTO employees VALUES (2, 104, 'David', 5500);
COMMIT;
查询语句

sql

复制代码
SELECT *
FROM (
    SELECT 
        dept_id,
        emp_id,
        emp_name,
        salary,
        ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY emp_id) as rn
    FROM 
        employees
)
WHERE rn = 1;
代码解释
  1. 子查询部分
    • ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY emp_id)PARTITION BY dept_id 表示按照 dept_id 进行分组,ORDER BY emp_id 表示在每个分组内按照 emp_id 进行排序。ROW_NUMBER() 会为每个分组内的记录依次分配一个行号。
  2. 外层查询部分
    • WHERE rn = 1:筛选出行号为 1 的记录,即每组的第一条记录。

方法二:使用KEEP函数(适用于聚合查询)

KEEP 函数可以在聚合函数中使用,用于根据指定的排序规则选择特定的值。

查询语句

sql

复制代码
SELECT 
    dept_id,
    MIN(emp_id) KEEP (DENSE_RANK FIRST ORDER BY emp_id) as emp_id,
    MIN(emp_name) KEEP (DENSE_RANK FIRST ORDER BY emp_id) as emp_name,
    MIN(salary) KEEP (DENSE_RANK FIRST ORDER BY emp_id) as salary
FROM 
    employees
GROUP BY 
    dept_id;
代码解释
  • MIN(emp_id) KEEP (DENSE_RANK FIRST ORDER BY emp_id):在每个 dept_id 分组内,按照 emp_id 排序,选择排序后的第一条记录的 emp_id 值。
  • 同样的逻辑适用于 emp_namesalary 字段。

方法三:使用FETCH FIRST(Oracle 12c 及以上版本)

如果只是想简单地获取每组的第一条记录,可以结合 GROUP BY 和子查询,然后使用 FETCH FIRST 来获取每组的第一条。

查询语句

sql

复制代码
SELECT *
FROM (
    SELECT 
        dept_id,
        emp_id,
        emp_name,
        salary
    FROM 
        employees
    ORDER BY 
        dept_id, emp_id
)
GROUP BY 
    dept_id
HAVING 
    emp_id = MIN(emp_id)
FETCH FIRST 1 ROW WITH TIES;
代码解释
  1. 子查询部分 :对 employees 表按照 dept_idemp_id 进行排序。
  2. 外层查询部分
    • GROUP BY dept_id:按照 dept_id 进行分组。
    • HAVING emp_id = MIN(emp_id):筛选出每组中 emp_id 最小的记录。
    • FETCH FIRST 1 ROW WITH TIES:获取每组的第一条记录,如果有并列的情况也会一并返回。

以上三种方法都可以实现获取 GROUP BY 分组后每组的第一条记录,你可以根据实际需求和数据库版本选择合适的方法。

mysql 取Group By 第一条

在 MySQL 中,若要获取 GROUP BY 分组后的每组第一条记录,有多种实现方式,以下为你详细介绍常见的几种方法。

示例表结构和数据

首先创建一个示例表并插入一些数据,后续的查询都基于这个表展开:

sql

复制代码
-- 创建示例表
CREATE TABLE employees (
    dept_id INT,
    emp_id INT,
    emp_name VARCHAR(100),
    salary DECIMAL(10, 2),
    PRIMARY KEY (emp_id)
);

-- 插入示例数据
INSERT INTO employees (dept_id, emp_id, emp_name, salary) VALUES
(1, 101, 'Alice', 5000.00),
(1, 102, 'Bob', 6000.00),
(2, 103, 'Charlie', 4500.00),
(2, 104, 'David', 5500.00);

方法一:使用 JOIN 和子查询

这种方法先通过子查询找出每组的最小 emp_id,然后将原表与子查询结果进行连接,从而获取每组的第一条记录。

sql

复制代码
SELECT e.*
FROM employees e
JOIN (
    -- 子查询:找出每个部门的最小 emp_id
    SELECT dept_id, MIN(emp_id) AS min_emp_id
    FROM employees
    GROUP BY dept_id
) sub ON e.dept_id = sub.dept_id AND e.emp_id = sub.min_emp_id;

代码解释

  • 子查询 SELECT dept_id, MIN(emp_id) AS min_emp_id FROM employees GROUP BY dept_id 会按照 dept_id 分组,并找出每组中 emp_id 最小的记录。
  • 主查询将 employees 表(e)与子查询结果(sub)进行连接,连接条件是 dept_id 相等且 emp_id 等于子查询中找出的最小 emp_id,这样就能获取每组的第一条记录。

方法二:使用 ROW_NUMBER() 窗口函数(MySQL 8.0 及以上版本支持)

ROW_NUMBER() 窗口函数可以为结果集中的每一行分配一个唯一的行号,我们可以根据分组字段和排序字段为每组内的记录编号,然后筛选出行号为 1 的记录。

sql

复制代码
SELECT *
FROM (
    -- 子查询:为每个部门的记录分配行号
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY emp_id) AS rn
    FROM 
        employees
) sub
WHERE rn = 1;

代码解释

  • 子查询中的 ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY emp_id) 会按照 dept_id 进行分组,在每个分组内按照 emp_id 排序,并为每行分配一个行号。
  • 主查询通过 WHERE rn = 1 筛选出行号为 1 的记录,即每组的第一条记录。

方法三:使用 EXISTS 子查询

此方法通过 EXISTS 子查询来判断当前记录是否为每组的第一条记录。

sql

复制代码
SELECT e1.*
FROM employees e1
WHERE NOT EXISTS (
    -- 子查询:判断是否存在 emp_id 更小且 dept_id 相同的记录
    SELECT 1
    FROM employees e2
    WHERE e2.dept_id = e1.dept_id AND e2.emp_id < e1.emp_id
);

代码解释

  • 对于 employees 表中的每一条记录 e1,子查询会检查是否存在另一条记录 e2,其 dept_ide1 相同,但 emp_id 更小。
  • 如果不存在这样的记录,说明 e1 是该组中 emp_id 最小的记录,即每组的第一条记录,会被主查询返回。

以上三种方法各有优劣,你可以根据实际的 MySQL 版本和数据情况选择合适的方法来获取 GROUP BY 分组后的每组第一条记录。

相关推荐
jiayou641 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
李广坤2 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
爱可生开源社区3 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1773 天前
《从零搭建NestJS项目》
数据库·typescript
加号34 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏4 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐4 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再4 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip
tryCbest4 天前
数据库SQL学习
数据库·sql
jnrjian4 天前
ORA-01017 查找机器名 用户名 以及library cache lock 参数含义
数据库·oracle