不要评判我,我是SQL查询的新手。我得到了计划,如下图所示。因此,有2个表,第一个Employees包含EmployeeID,FirstName,LastName,DateOfBirth和DepartmentID。第二个叫做Department,包含DepartmentID和DepartmentName。
我想为每个包含20名以上员工的部门中最老的员工返回FirstName,LastName和DepartmentName。
我的解决方案是以下查询:
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 error
每个派生表必须拥有它自己的别名。
我尝试在每个派生表上添加别名,但结果仍然相同。
请帮帮我。
此外,如果有人有不同的解决方案,请分享。
谢谢。
添加哪个草莓要求,Create
查询
CREATE TABLE Employees
(
EmployeeID int,
FirstName varchar(10),
LastName varchar(15),
DateOfBirth date,
DeparmentID int
)
CREATE TABLE Department
(
DepartmentID int,
DepartmentName varchar(15)
)
答案 0 :(得分:2)
由于格式不一致,您的查询很难阅读。所以我会按照以下方式清理它:
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
在上述解决方案中需要注意的一点是,如果2名员工因部门中最老的而被捆绑,则两者都将被退回。
这种方法在结构上与您的方法类似,但您也可以从另一个方向处理问题。
我会留给你试试。我怀疑查询会更简单一些。
答案 1 :(得分:0)
以下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)
);
按照您的班级图表,每个员工都有一个部门。那么,是使用INNER JOIN
的原因。我认为以下查询可以执行您想要的操作:
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
你改善了它的表现!