如何克服MySQL的子查询返回多个1行“的错误,并选择所有相关记录
表创建如何克服MySQL的子查询返回多个1行“的错误,并选择所有相关记录
CREATE TABLE `users` (
`id` INT UNSIGNED NOT NULL,
`name` VARCHAR(100) NOT NULL,
PRIMARY KEY(`id`)
);
CREATE TABLE `email_address` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`email_address` VARCHAR(50) NOT NULL,
INDEX pn_user_index(`user_id`),
FOREIGN KEY (`user_id`) REFERENCES users(`id`) ON DELETE CASCADE,
PRIMARY KEY(`id`)
);
数据插入
INSERT INTO users (id, name) VALUES (1, 'Mark'), (2, 'Tom'), (3, 'Robin');
INSERT INTO email_address (user_id, email_address) VALUES
(1, '[email protected]'), (1, '[email protected]'), (1, '[email protected]'),
(2, '[email protected]'), (2, '[email protected]'), (2, '[email protected]'),
(3, '[email protected]'), (3, '[email protected]'), (3, '[email protected]');
SQL查询
SELECT usr.name AS name
, (SELECT email.email_address
FROM email_address AS email
WHERE email.user_id = usr.id) AS email
FROM users AS usr;
通过使用上面我的MySQL查询,我如何避免MySQL错误'子查询返回多于一行'并为特定用户选择所有相关电子邮件地址,如下所示。谢谢。
+----------+-------------------------------------------------+
| name | email |
+----------+-------------------------------------------------+
| Mark | [email protected], [email protected], [email protected] |
| Tom | [email protected], [email protected], [email protected] |
| Robin | [email protected], [email protected], [email protected] |
+----------+----------+--------------------------------------+
GROUP_CONCAT
与SEPARATOR
和简化查询了一下:
SELECT users.name AS name,
(SELECT GROUP_CONCAT(email_address.email_address SEPARATOR ', ')
FROM email_address
WHERE email_address.user_id = users.id) AS email
FROM users
参考:https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat
你在email_address表上做了一个不明确的subselect语句。换句话说:您正在尝试在您的子选择中选择多行来进行单行选择。考虑一下,我会问你这个问题:“数据库如何用你的查询来决定选择哪个电子邮件地址?”答案是它不能,因为你的查询没有指定使用哪个电子邮件地址。因此你的错误。
您可以将您的子选择限制为1个值。下面是如何可能看:
SELECT usr.name AS name,
(SELECT email.email_address
FROM email_address AS email
WHERE email.user_id = usr.id
LIMIT 1)
AS email
FROM users AS usr;
不过,你最好的选择可能是通过电子邮件发送给潜在的电子邮件所有。为此,你需要一个JOIN
条款可能被结构是这样的:
SELECT usr.name AS name, addr.email AS email
FROM users AS usr
LEFT JOIN email_address AS addr ON (addr.user_id=usr.id);
这将会给你一个选择行的是用户和电子邮件地址的组合。这意味着您将为具有多个电子邮件地址关联的任何用户返回多行。那就是你可以迭代所有返回的行并发送所有用户的电子邮件。如果有某种方法可以识别主要电子邮件地址,那么您可能只需向主要电子邮件发送电子邮件。
我很想听听为什么这是被拒绝的。对负面意见的反馈似乎对每个人都是浪费时间。 – SwampDev
我宁愿做这样的而不是使用子查询
select
GROUP_CONCAT(ea.email_address) as emails,
u.name
from
users u
left join email_address ea ON (u.id=ea.user_id)
group by u.id,u.name
GROUP_CONCAT是一个possibility-但我真的怀疑这是否是一种有用的方式来返回数据。 – Strawberry