复杂的MySQL没有返回我需要的结果

时间:2018-04-22 23:10:24

标签: mysql

TL:博士 我需要从一个表中获取每个员工的最新行,并将其与另一个表中的每个员工的多个行匹配。我能够从一个表中获得每个员工的最新条目,但无法从第二个表中提取数据。

详细说明:

前两个表显示了我数据库中的一些代表性数据。此处显示的数据和表格是我的完整架构和数据集的片段。 (表格:'员工'和'employee_payrollhours')

employee_number:这是个人员工的身份证号码 inserted_at:这是将记录保存到数据库时的日期/时间戳 datetime_in:这是员工开始轮班的日期/时间

SELECT employee_number, last_name, inserted_at FROM employees;
TABLE:  employees
+-----------------+-------------+---------------------+
| employee_number |  last_name  | inserted_at         |
+-----------------+-------------+---------------------+
|       123456789 | Lastone     | 2018-02-26 22:26:38 |
|       123456789 | Lastone     | 2018-03-15 15:16:14 |
|       123456789 | Lastone     | 2018-03-15 20:57:23 |
|       123456789 | Lastone     | 2018-04-16 00:10:27 |
|       223456789 | Lasttwo     | 2018-04-16 03:37:49 |
|       270000001 | Lastthree   | 2018-04-06 22:42:50 |
|       270000001 | Lastthree   | 2018-04-17 14:10:01 |
+-----------------+-------------+---------------------+


SELECT employee_number, datetime_in FROM employee_payrollhours
TABLE:  employee_payrollhours
+-----------------+---------------------+
| employee_number | datetime_in         |
+-----------------+---------------------+
|       123456789 | 2018-04-06 08:00:00 |
|       123456789 | 2018-04-08 08:00:00 |
|       123456789 | 2018-04-10 08:00:00 |
|       123456789 | 2018-04-15 08:00:00 |
|       123456789 | 2018-04-17 08:00:00 |
|       123456789 | 2018-04-19 08:00:00 |
|       223456789 | 2018-04-06 08:00:00 |
|       223456789 | 2018-04-08 08:00:00 |
|       223456789 | 2018-04-10 08:00:00 |
|       223456789 | 2018-04-15 08:00:00 |
|       223456789 | 2018-04-17 08:00:00 |
|       223456789 | 2018-04-19 08:00:00 |
|       270000001 | 2018-04-07 08:00:00 |
|       270000001 | 2018-04-09 08:00:00 |
|       270000001 | 2018-04-11 08:00:00 |
|       270000001 | 2018-04-16 08:00:00 |
+-----------------+---------------------+

从员工那里为每位员工获得一行

SELECT * FROM employees GROUP BY last_name

并从employees表中获取每位员工的最新条目。

SELECT * FROM employees e1
WHERE Inserted_at = 
    (SELECT MAX(e2.Inserted_at)
    FROM employees e2
    WHERE e1.Employee_Number = e2.Employee_Number)
+-----------------+-------------+---------------------+
| employee_number |  last_name  | inserted_at         |
+-----------------+-------------+---------------------+
|       123456789 | Lastone     | 2018-04-16 00:10:27 |
|       223456789 | Lasttwo     | 2018-04-16 03:37:49 |
|       270000001 | Lastthree   | 2018-04-17 14:10:01 |
+-----------------+-------------+---------------------+

这就是我想要的。我希望显示“员工”中每位员工的最新条目以及“employee_payrollhours”表中的相应员工数据。

+-------------------+---------------------+
|     last_name     | datetime_in         |
+-------------------+---------------------+
|       Lastone     | 2018-04-06 08:00:00 |
|       Lastone     | 2018-04-08 08:00:00 |
|       Lastone     | 2018-04-10 08:00:00 |
|       Lastone     | 2018-04-15 08:00:00 |
|       Lastone     | 2018-04-17 08:00:00 |
|       Lastone     | 2018-04-19 08:00:00 |
|       Lasttwo     | 2018-04-06 08:00:00 |
|       Lasttwo     | 2018-04-08 08:00:00 |
|       Lasttwo     | 2018-04-10 08:00:00 |
|       Lasttwo     | 2018-04-15 08:00:00 |
|       Lasttwo     | 2018-04-17 08:00:00 |
|       Lasttwo     | 2018-04-19 08:00:00 |
|       Lastthree   | 2018-04-07 08:00:00 |
|       Lastthree   | 2018-04-09 08:00:00 |
|       Lastthree   | 2018-04-11 08:00:00 |
|       Lastthree   | 2018-04-16 08:00:00 |
+-------------------+---------------------+

此查询给出了错误“子查询返回超过1行”

SELECT employees.*, employee_payrollhours.*
FROM employees, employee_payrollhours
WHERE employee_payrollhours.employee_number = (select employee_number from employees group by last_name);

此查询为我提供了混合数据。

SELECT employees.last_name, employees.employee_number, employee_payrollhours.employee_number, employee_payrollhours.datetime_in
FROM employees, employee_payrollhours
WHERE employee_payrollhours.employee_number = employees.employee_number;

并且此查询为我提供了零返回结果

SELECT * FROM employees e1, employee_payrollhours
WHERE `e1`.`Inserted_at` = 
    (SELECT MAX(e2.Inserted_at)
    FROM employees e2
    WHERE e1.Employee_Number = e2.Employee_Number)
    AND (`e1`.`Inserted_at` = 
    (SELECT MAX(e2.Inserted_at)
    FROM employees e2
    WHERE e1.Employee_Number = e2.Employee_Number)) = employee_payrollhours.Employee_Number;

有人请给我一些指导,告诉我如何处理这个问题,找到我需要的查询吗?

提前谢谢。

3 个答案:

答案 0 :(得分:0)

我认为这个查询(SQLFiddle)会做你想做的事情:

select e.last_name, e.most_recent, p.datetime_in
from (select employee_number, last_name, max(inserted_at) as most_recent from employees group by employee_number) e
left join employee_payrollhours p
on p.employee_number = e.employee_number

输出:

last_name   most_recent             datetime_in
Lastone     2018-04-16 00:10:27     2018-04-06 08:00:00
Lastone     2018-04-16 00:10:27     2018-04-08 08:00:00
Lastone     2018-04-16 00:10:27     2018-04-10 08:00:00
Lastone     2018-04-16 00:10:27     2018-04-15 08:00:00
Lastone     2018-04-16 00:10:27     2018-04-17 08:00:00
Lastone     2018-04-16 00:10:27     2018-04-19 08:00:00
Lasttwo     2018-04-16 03:37:49     2018-04-06 08:00:00
Lasttwo     2018-04-16 03:37:49     2018-04-08 08:00:00
Lasttwo     2018-04-16 03:37:49     2018-04-10 08:00:00
Lasttwo     2018-04-16 03:37:49     2018-04-15 08:00:00
Lasttwo     2018-04-16 03:37:49     2018-04-17 08:00:00
Lasttwo     2018-04-16 03:37:49     2018-04-19 08:00:00
Lastthree   2018-04-17 14:10:01     2018-04-07 08:00:00
Lastthree   2018-04-17 14:10:01     2018-04-09 08:00:00
Lastthree   2018-04-17 14:10:01     2018-04-11 08:00:00
Lastthree   2018-04-17 14:10:01     2018-04-16 08:00:00

答案 1 :(得分:0)

当然有很多方法可以做到,而且我只会提出其中一个。这里的诀窍是从inserted_at表中获取employees的最后一个条目。一种方法是使用group by进行max查询,但我们将无法加入employee_payrollhours表。但是,我们可以使用一个技巧,我们使用left outer join employees使用具有较大inserted_at的条件,然后仅过滤连接为空的记录,这将给出我们与group by查询的结果相同但我们仍然可以加入employee_payrollhours并获得想要的结果。

像这样:

select e1.*, eprh.* from employees e1
  left outer join employees e2 on
    e1.employee_number = e2.employee_number and
    e2.inserted_at > e1.inserted_at
  left join employees_payrollhours eprh on
    eprh.employee_number = e1.employee_number
where e2.employee_number is null

答案 2 :(得分:0)

非常感谢你们(截至撰写本文时)。我显然需要更多的MySQL练习。

在评论中,我解释了为什么我选择了我的答案。

我在我的应用程序中尝试了两种解决方案。我选择的那个允许那些没有进入任何时间的员工仍然被展示。这包括在特定时间段内可能尚未工作但仍会在结果中显示的兼职员工。