3

表创建

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, 'mark@gmail.com'), (1, 'mark@yahoo.com'), (1, 'mark@msn.com'), 
(2, 'tom@gmail.com'), (2, 'tom@yahoo.com'), (2, 'tom@msn.com'),
(3, 'robin@gmail.com'), (3, 'robin@yahoo.com'), (3, 'robin@msn.com');

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 错误“子查询返回超过 1 行”并选择特定用户的所有相关电子邮件地址,如下所示。谢谢。

+----------+-------------------------------------------------+
|   name   |                     email                       |
+----------+-------------------------------------------------+
|   Mark   | mark@gmail.com, mark@yahoo.com, mark@msn.com    |
|   Tom    | tom@gmail.com, tom@yahoo.com, tom@msn.com       |
|   Robin  | robin@gmail.com, robin@yahoo.com, robin@msn.com |                   
+----------+----------+--------------------------------------+
4

3 回答 3

2

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

于 2017-01-03T02:45:22.487 回答
0

您在 email_address 表上做了一个模棱两可的子选择语句。换句话说:您试图在子选择中选择多行以进行单行选择。想一想,我会问你这个问题:“数据库如何根据你的查询决定选择哪个电子邮件地址?” 答案是不能,因为您的查询没有指定要使用的电子邮件地址。因此你的错误。

您可以将子选择限制为 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);

这将为您提供由用户和电子邮件地址组合而成的行选择。这意味着您将为具有多个电子邮件地址关联的任何用户返回多行。那就是您可以遍历所有返回的行并通过电子邮件发送所有用户的电子邮件。如果有某种方法可以识别主电子邮件地址,那么您可能只需向主电子邮件地址发送电子邮件。

于 2017-01-03T02:30:18.953 回答
0

我宁愿这样做而不是使用子查询

    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
于 2017-01-03T02:59:28.133 回答