我正在迁移一个新的数据库,以将一对多关系更改为多对多关系(以及改进列命名方案)。 [编辑:我为此创建了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
具体而言,我在people
和groups
之间创建链接表时遇到问题。
我已经创建了people
和groups
表:
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。)
Here是 工作的SQLFiddle。为什么它在我的phpmyadmin中不起作用?
答案 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版开始),以禁止您刚刚执行的查询类型。
您的查询,版本5.7.14服务器上没有GROUP BY
但order by newGroups.id,people.id
: