【问题标题】:left outer join does not display expected result in postgres左外连接未在 postgres 中显示预期结果
【发布时间】:2017-09-21 07:30:59
【问题描述】:

我有两张表,一张用于存储 mont 的日期,另一张用于保存员工的出勤详细信息

在我的情况下,出席天数表有 31 条记录 在员工考勤表中,一名员工有 29 条,另一名员工有 8 条记录,共 37 条记录 数据如下

create table attendance_days 
(id serial primary key not null, 
attendance_date date );



INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-01');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-02');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-03');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-04');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-05');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-06');

INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-07');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-08');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-09');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-10');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-11');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-12');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-13');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-14');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-15');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-16');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-17');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-18');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-19');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-20');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-21');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-22');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-23');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-24');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-25');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-26');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-27');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-28');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-29');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-30');
INSERT INTO attendance_days  (attendance_date) VALUES ('2017-08-31');`

`

create table  employee_attendance
 (id serial primary key not null, 
 attendance_day_id integer ,
 employee_id integer,
 first_in_time timestamp,
 last_out_time timestamp );


INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 1, 407, '2017-08-01 09:30:00', '2017-08-01 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (2, 407, '2017-08-02 09:30:00', '2017-08-02 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 3, 407, '2017-08-03 09:30:00', '2017-08-03 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (4, 407, '2017-08-04 09:30:00', '2017-08-04 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 5, 407, '2017-08-05 09:30:00', '2017-08-05 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 6, 407, '2017-08-06 09:30:00', '2017-08-06 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 7, 407, '2017-08-07 09:30:00', '2017-08-07 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 8, 407, '2017-08-08 09:30:00', '2017-08-08 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 9, 407, '2017-08-09 09:30:00', '2017-08-09 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 12, 407, '2017-08-12 09:30:00', '2017-08-12 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 13, 407, '2017-08-13 09:30:00', '2017-08-13 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 14, 407, '2017-08-14 09:30:00', '2017-08-14 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (15, 601, '2017-08-15 10:44:40', '2017-08-15 10:47:36');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 15, 407, '2017-08-15 09:30:00', '2017-08-15 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 16, 407, '2017-08-16 09:30:00', '2017-08-16 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 17, 407, '2017-08-17 09:30:00', '2017-08-17 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 18, 407, '2017-08-18 09:30:00', '2017-08-18 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (18, 601, '2017-08-18 08:12:41', '2017-08-19 07:57:12');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 19, 601, '2017-08-19 07:57:12', '2017-08-19 20:14:01');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 19, 407, '2017-08-19 09:30:00', '2017-08-19 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 20, 407, '2017-08-20 09:30:00', '2017-08-20 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 21, 407, '2017-08-21 09:30:00', '2017-08-21 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 22, 601, '2017-08-22 08:07:00', '2017-08-22 20:43:10');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 22, 407, '2017-08-22 09:30:00', '2017-08-22 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 23, 407, '2017-08-23 09:30:00', '2017-08-23 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (24, 407, '2017-08-24 09:30:00', '2017-08-24 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 24, 601, '2017-08-24 08:06:58', '2017-08-24 20:03:44');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 25, 407, '2017-08-25 09:30:00', '2017-08-25 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 26, 601, '2017-08-26 09:14:24', '2017-08-26 20:21:32');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 26, 407, '2017-08-26 09:30:00', '2017-08-26 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 27, 407, '2017-08-27 09:30:00', '2017-08-27 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 27, 601, '2017-08-27 08:48:09', '2017-08-28 07:55:24');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (28, 407, '2017-08-28 09:30:00', '2017-08-28 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 29, 407, '2017-08-29 09:30:00', '2017-08-29 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES ( 29, 601, '2017-08-29 08:09:44', '2017-08-29 20:04:26');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (30, 407, '2017-08-30 09:30:00', '2017-08-30 20:00:00');
INSERT INTO employee_attendance( attendance_day_id, employee_id, first_in_time, last_out_time) VALUES (31, 407, '2017-08-31 09:30:00', '2017-08-31 20:00:00');`

第一个表有 31 条记录(8 月 31 天)第二个表有 37 条记录(employee_id 407 有 29 条记录,employee_id 601 有 8 条记录

我执行了以下查询

SELECT * 
FROM attendance_days
  LEFT OUTER JOIN employee_attendance 
               ON employee_attendance.attendance_day_id = attendance_days.id 

它只返回 37 行,但我预计 62 行(员工每行 31 行)

我无法理解问题

【问题讨论】:

  • 你能解释一下为什么你期望 62 行吗?
  • 第一个表31行第二个表,第二个表有两个员工的记录

标签: sql postgresql-9.3 outer-join


【解决方案1】:

postgres 会为每个出勤日期的 id 找到一个匹配的行,因此没有理由创建人为的命中(看起来像“id, admission_date, null, null, null, null, null”)。

实际上,您期待的结果类似于“id, admission_date, null, null, employee_id, null, null”。

因此,您必须构建一个笛卡尔乘积,该乘积是“出勤天数.id”和“雇员 ID”(来自“员工表”),它为您提供了两者的所有组合(62 行)。 可以将此笛卡尔积与employee_attendance 表进行外部联接以产生所需的结果。

【讨论】:

  • 但是如果我从employee_attendance 表中删除employee_id 407 的记录,它将显示31 条记录
  • 是的,6 行具有匹配的 id,25 行具有不匹配的 id。您期望得到一个结果集,其中包含每个员工 ID 的出勤日的完整列表,以及他们所在的开始和结束时间。这意味着每一行至少应显示:出勤日.id、出勤日期 employee_id。
  • 现在,如果您查看查询结果(不包括员工 407),您会发现大多数行中都缺少employee_id。这就是为什么您必须(左外)加入天数和员工的笛卡尔积(员工和天数的所有组合的列表)。
猜你喜欢
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 1970-01-01
相关资源
最近更新 更多