Mysql 如果部门有超过20名员工,则返回部门中最老员工的信息

Mysql 如果部门有超过20名员工,则返回部门中最老员工的信息,mysql,sql,subquery,Mysql,Sql,Subquery,不要评判我,我是SQL查询新手。我得到了一个方案,如下图所示。所以,有两个表,第一个表包含EmployeeID、FirstName、LastName、DateOfBirth和DepartmentID。第二个称为Department,包含DepartmentID和DepartmentName 我想返回每个部门中超过20名员工的最老员工的名字、姓氏和部门名称 我的解决方案是以下查询: SELECT FirstName, LastName, DepartmentName FROM employees

不要评判我,我是SQL查询新手。我得到了一个方案,如下图所示。所以,有两个表,第一个表包含EmployeeID、FirstName、LastName、DateOfBirth和DepartmentID。第二个称为Department,包含DepartmentID和DepartmentName

我想返回每个部门中超过20名员工的最老员工的名字、姓氏和部门名称

我的解决方案是以下查询:

SELECT FirstName, LastName, DepartmentName
FROM employees
LEFT JOIN department
ON employees.DepartmentID = department.DepartmentID
    WHERE (employees.DateOfBirth = 
(SELECT MIN(employees.DateOfBirth ) FROM (
SELECT *FROM employees WHERE employees.DepartmentID IN ( 
SELECT employees.DepartmentID FROM employees GROUP BY DepartmentID HAVING COUNT(*) > 20)));
我认为这个逻辑很好,因为内部的
SELECT
语句将返回每个部门超过20名员工的ID,外部的应该返回最老的员工

我遇到的问题是,当我尝试执行此查询时,它返回
SQL错误
每个派生表都必须有自己的别名。 我尝试在每个派生表上放置别名,但结果仍然是一样的。 请帮我拿这个

另外,如果有人有不同的解决方案,请分享

多谢各位。 草莓要求的添加,
创建
查询

CREATE TABLE Employees
(
EmployeeID int, 
FirstName varchar(10),
LastName varchar(15),
DateOfBirth date,
DeparmentID int
)

CREATE TABLE Department
(
DepartmentID int, 
DepartmentName varchar(15)
)

由于格式不一致,您的查询很难读取。因此,我将按如下方式清理它:

SELECT  FirstName, LastName, DepartmentName
FROM    employees
        LEFT JOIN department
        ON employees.DepartmentID = department.DepartmentID
WHERE   (employees.DateOfBirth = 
        (
        SELECT  MIN(employees.DateOfBirth)
        FROM    (
                SELECT  *
                FROM    employees
                WHERE   employees.DepartmentID IN (
                        --Departments with more than 20 employees
                        SELECT  employees.DepartmentID
                        FROM    employees
                        GROUP BY DepartmentID
                        HAVING COUNT(*) > 20)
                ) -- You need an alias here.
                  -- Also from this point you were missing closing brackets.
您的查询存在问题:

  • 显然,缺少别名和右括号意味着您甚至无法测试查询
  • 另外
    SELECT MIN(employees.DateOfBirth)
    只返回一个值。不是每个部门的值
  • 因此,您的总体结果只包括所有“大”部门中最老的员工。(除非每个部门中年龄最大的员工恰好有相同的出生日期。)
  • 如果任何员工的出生日期恰好与大部门中年龄最大的员工的出生日期相同,则还可能包括来自较小部门的结果。而且那个员工甚至不必是他们部门里年龄最大的
  • 由于使用了过多的子查询,您的效率也会降低
CTE(公共表表达式)非常擅长简化复杂查询。但我不知道mysql是否支持它们。所以这个解决方案仍然使用子查询

SELECT  e.FirstName, e.LastName, d.DepartmentName
FROM    employees e -- I prefer short aliases
        INNER JOIN (
        -- This sub-query returns the earliest birth date within each
        -- big department. This needs to be an aliased query so you
        -- can join to other tables for your desired columns.
        SELECT  DepartmentID, MIN(DateOfBirth) AS MinDOB -- Must alias column
        FROM    employees
        WHERE   DepartmentID IN (
                -- Big departments
                SELECT  DepartmentID
                FROM    employees
                GROUP BY DepartmentID
                HAVING COUNT(*) > 20
                )
        GROUP BY DepartmentID
        ) ddob -- Alias Department Date of Birth
        -- As a result of inner joining to ddob your employees
        -- will be filtered to only those that match the relevant
        -- ones identified in the query.
        ON  e.DepartmentID = ddob.DepartmentID
        AND e.DateOfBirth = ddob.MinDOB
        INNER JOIN Department d
        ON  d.DepartmentID = e.DepartmentID
在上述解决方案中需要注意的是,如果一个部门中有两名员工年龄最大,那么这两名员工都将被退回

这种方法在结构上与您的方法类似,但您也可以从另一个方向来处理问题

  • 开始在所有部门招募年龄最大的员工
  • 并且只在最后根据部门大小过滤结果

我会让你试试看。我想查询会简单一点。

由于格式不一致,您的查询很难阅读。因此,我将按如下方式清理它:

SELECT  FirstName, LastName, DepartmentName
FROM    employees
        LEFT JOIN department
        ON employees.DepartmentID = department.DepartmentID
WHERE   (employees.DateOfBirth = 
        (
        SELECT  MIN(employees.DateOfBirth)
        FROM    (
                SELECT  *
                FROM    employees
                WHERE   employees.DepartmentID IN (
                        --Departments with more than 20 employees
                        SELECT  employees.DepartmentID
                        FROM    employees
                        GROUP BY DepartmentID
                        HAVING COUNT(*) > 20)
                ) -- You need an alias here.
                  -- Also from this point you were missing closing brackets.
您的查询存在问题:

  • 显然,缺少别名和右括号意味着您甚至无法测试查询
  • 另外
    SELECT MIN(employees.DateOfBirth)
    只返回一个值。不是每个部门的值
  • 因此,您的总体结果只包括所有“大”部门中最老的员工。(除非每个部门中年龄最大的员工恰好有相同的出生日期。)
  • 如果任何员工的出生日期恰好与大部门中年龄最大的员工的出生日期相同,则还可能包括来自较小部门的结果。而且那个员工甚至不必是他们部门里年龄最大的
  • 由于使用了过多的子查询,您的效率也会降低
CTE(公共表表达式)非常擅长简化复杂查询。但我不知道mysql是否支持它们。所以这个解决方案仍然使用子查询

SELECT  e.FirstName, e.LastName, d.DepartmentName
FROM    employees e -- I prefer short aliases
        INNER JOIN (
        -- This sub-query returns the earliest birth date within each
        -- big department. This needs to be an aliased query so you
        -- can join to other tables for your desired columns.
        SELECT  DepartmentID, MIN(DateOfBirth) AS MinDOB -- Must alias column
        FROM    employees
        WHERE   DepartmentID IN (
                -- Big departments
                SELECT  DepartmentID
                FROM    employees
                GROUP BY DepartmentID
                HAVING COUNT(*) > 20
                )
        GROUP BY DepartmentID
        ) ddob -- Alias Department Date of Birth
        -- As a result of inner joining to ddob your employees
        -- will be filtered to only those that match the relevant
        -- ones identified in the query.
        ON  e.DepartmentID = ddob.DepartmentID
        AND e.DateOfBirth = ddob.MinDOB
        INNER JOIN Department d
        ON  d.DepartmentID = e.DepartmentID
在上述解决方案中需要注意的是,如果一个部门中有两名员工年龄最大,那么这两名员工都将被退回

这种方法在结构上与您的方法类似,但您也可以从另一个方向来处理问题

  • 开始在所有部门招募年龄最大的员工
  • 并且只在最后根据部门大小过滤结果

我会让你试试看。我猜想查询会简单一点。

以下SQL脚本与您的类图相对应:

CREATE TABLE Departments (
 DepartmentID int AUTO_INCREMENT PRIMARY KEY, 
 DepartmentName varchar(15)
);

CREATE TABLE Employees (
 EmployeeID int AUTO_INCREMENT PRIMARY KEY, 
 FirstName varchar(10),
 LastName varchar(15),
 DateOfBirth date,
 DepartmentID int,
 FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID)
);
按照类图,每个员工都有一个部门。因此,这就是使用
内部联接的原因。我认为以下查询符合您的要求:

SELECT ee.FirstName, ee.LastName, ee.DateOfBirth, t.DepartmentName 
FROM
( 
     SELECT e.DepartmentID, d.DepartmentName, MIN(e.DateOfBirth) AS DateOfBirth 
     FROM Employees AS e
     INNER JOIN Departments AS d ON e.DepartmentID = d.DepartmentID
     WHERE e.DepartmentID IN (
         SELECT DepartmentID 
         FROM Employees 
         GROUP BY DepartmentID HAVING COUNT(DepartmentID) > 20
     )
     GROUP BY e.DepartmentID
) AS t
INNER JOIN Employees AS ee
WHERE ee.DepartmentID = t.DepartmentID AND ee.DateOfBirth = t.DateOfBirth
输出示例:

FirstName   LastName    DateOfBirth DepartmentName
fisrt14     last14      02/01/2000  SI
fisrt31     last31      12/01/2003  Finance

你提高了它的性能

以下SQL脚本对应于您的类图:

CREATE TABLE Departments (
 DepartmentID int AUTO_INCREMENT PRIMARY KEY, 
 DepartmentName varchar(15)
);

CREATE TABLE Employees (
 EmployeeID int AUTO_INCREMENT PRIMARY KEY, 
 FirstName varchar(10),
 LastName varchar(15),
 DateOfBirth date,
 DepartmentID int,
 FOREIGN KEY (DepartmentID) REFERENCES Departments(DepartmentID)
);
按照类图,每个员工都有一个部门。因此,这就是使用
内部联接的原因。我认为以下查询符合您的要求:

SELECT ee.FirstName, ee.LastName, ee.DateOfBirth, t.DepartmentName 
FROM
( 
     SELECT e.DepartmentID, d.DepartmentName, MIN(e.DateOfBirth) AS DateOfBirth 
     FROM Employees AS e
     INNER JOIN Departments AS d ON e.DepartmentID = d.DepartmentID
     WHERE e.DepartmentID IN (
         SELECT DepartmentID 
         FROM Employees 
         GROUP BY DepartmentID HAVING COUNT(DepartmentID) > 20
     )
     GROUP BY e.DepartmentID
) AS t
INNER JOIN Employees AS ee
WHERE ee.DepartmentID = t.DepartmentID AND ee.DateOfBirth = t.DateOfBirth
输出示例:

FirstName   LastName    DateOfBirth DepartmentName
fisrt14     last14      02/01/2000  SI
fisrt31     last31      12/01/2003  Finance

你提高了它的性能

哇,年龄歧视查询-SOI上的第一个如果派生表需要别名,请给它一个别名!就这么简单。也就是说,这是一个很难看的问题。吃午饭的时间-评论删除,因为Me()将返回最早的生日,如果你喜欢,考虑下面这个简单的两步行动:1。如果您还没有这样做,请提供适当的CREATE和INSERT语句(和/或SQLFIDLE),以便我们可以更轻松地复制问题。2.如果您还没有这样做,请提供与步骤1中提供的信息相对应的所需结果集。哇,年龄歧视查询-SOI上的第一个如果派生表需要别名,请为其指定别名!就这么简单。也就是说,这是一个很难看的问题。吃午饭的时间-评论删除,因为Me()将返回最早的生日,如果你喜欢,考虑下面这个简单的两步行动:1。如果您还没有这样做,请提供适当的CREATE和INSERT语句(和/或SQLFIDLE),以便我们可以更轻松地复制问题。2.如果您尚未这样做,请提供与步骤1中提供的信息相对应的所需结果集。您的答案不正确