Bootstrap

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_name 和 salary 字段。

方法三:使用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_id 和 emp_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_id 与 e1 相同,但 emp_id 更小。
  • 如果不存在这样的记录,说明 e1 是该组中 emp_id 最小的记录,即每组的第一条记录,会被主查询返回。

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

;