为什么我在Left Join上获得NULL值?

时间:2016-09-18 23:42:30

标签: mysql phpmyadmin

我正在迁移一个新的数据库,以将一对多关系更改为多对多关系(以及改进列命名方案)。 [编辑:我为此创建了SQLFiddle。]

oldDB                           newDB
=========================       =======================================
individuals                     people
 - individual_id                 - id
 - individual_name_first         - first_name
 - individual_name_last          - last_name
 - individual_name_other         - additional_identifier
 - individual_position           - role
 - individual_group_code         - (replaced with people-groups table)
(There are duplicate rows
 in this table for individ's
 who are in more than one
 group.)

groups                          groups
 - (no id in oldDB)              - id
 - group_code                    - short_name
 - group_name                    - full_name

                                people_groups
                                 - id
                                 - person_id
                                 - group_id
                                 - start_date
                                 - end_date

具体而言,我在peoplegroups之间创建链接表时遇到问题。

我已经创建了peoplegroups表:

CREATE TABLE IF NOT EXISTS people (
  id int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  first_name varchar(50) NOT NULL,
  last_name varchar(50) NOT NULL,
  additional_identifier varchar(50) DEFAULT NULL COMMENT 'In case of duplicate first and last names',
  role varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE newDB.people ADD UNIQUE `name` (last_name, first_name, additional_identifier);

INSERT INTO newDB.people
  (id, first_name, last_name, role)
SELECT
  individual_id, individual_name_last, individual_name_first, individual_position, COUNT(*)
FROM
  oldDB.individuals
GROUP BY
  individual_name_last, individual_name_first;

CREATE TABLE IF NOT EXISTS newDB.groups(
    id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    full_name VARCHAR(255) NOT NULL UNIQUE,
    short_name VARCHAR(255) NOT NULL UNIQUE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO newDB.groups
  (full_name, short_name)
SELECT
  group_name, group_code
FROM
  oldDB.groups;

接下来我会CREATE newDB.people-groups表,但首先我要确保SELECT正确的值:

SELECT
  newDB.groups.id 'group id',
  newDB.people.id 'person id',
  individual_group_code 'group short name',
  individual_name_last 'last name',
  individual_name_first 'first name'
FROM
  oldDB.individuals
LEFT JOIN
  newDB.groups ON(
    newDB.groups.short_name = oldDB.individuals.individual_group_code
   )
LEFT JOIN newDB.people ON (
  newDB.people.last_name = oldDB.individuals.individual_name_last 
    AND
  newDB.people.first_name = oldDB.individuals.individual_name_first
)
GROUP BY
  individual_name_last ASC,
  individual_name_first ASC,
  individual_group_code

第一个LEFT JOIN仅用于显示群组短名称以便于验证。 第二个LEFT JOIN非常重要:它应该允许从'person id'提取newDB.people.id输出。相反,我只是在该列中为所有输出行获取NULL。其他所有内容都正确显示。我错过了什么?

编辑:

期望的输出

这是我希望得到的。 (我通过用newDB.people.id 'person id'替换oldDB.individuals.individual_id 'person id'来生成它。举例来说,问题是人925和1232是两个不同组中的同一个人。新数据库简化了人员925。) This is the desired output

实际输出

这是我得到的: The out put with nulls

编辑2:

Here 工作的SQLFiddle。为什么它在我的phpmyadmin中不起作用?

1 个答案:

答案 0 :(得分:1)

您正在选择列表中执行包含5列非聚合列的group by(3列)。此外,重要的是,列输出中没有聚合。

MySQL将其视为distinct(对于3列)并将其在MRU高速缓存中遇到的第一行带回,如果没有高速缓存,则在聚簇索引或物理排序中遇到的第一行满足2个非分组列。

换句话说,这是一个用户错误。一个snafu。我建议您使用GROUP BY清除您的意图。

有点相关,请阅读与ONLY_FULL_GROUP_BY相关的我最近的答案Here。请参阅该链接底部的MySQL Handling of GROUP BY,在我看来,它是对MySQL允许的真实问题和非标准的掩盖,这些问题导致意外且难以解释违反该标准的数据。

那么MySQL开发团队做了什么?他们默认实现了标准(从5.7版开始),以禁止您刚刚执行的查询类型。

EDIT1

您的查询,版本5.7.14服务器上没有GROUP BYorder by newGroups.id,people.id

enter image description here