如何克服MySQL的子查询返回多个1行“的错误,并选择所有相关记录

如何克服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] |     
+----------+----------+--------------------------------------+ 
+1

GROUP_CONCAT是一个possibility-但我真的怀疑这是否是一种有用的方式来返回数据。 – Strawberry

GROUP_CONCATSEPARATOR和简化查询了一下:

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); 

这将会给你一个选择行的是用户和电子邮件地址的组合。这意味着您将为具有多个电子邮件地址关联的任何用户返回多行。那就是你可以迭代所有返回的行并发送所有用户的电子邮件。如果有某种方法可以识别主要电子邮件地址,那么您可能只需向主要电子邮件发送电子邮件。

+0

我很想听听为什么这是被拒绝的。对负面意见的反馈似乎对每个人都是浪费时间。 – 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