【问题标题】:mySQL complex SELECT query?mySQL 复杂的 SELECT 查询?
【发布时间】:2025-12-20 15:30:16
【问题描述】:

这是我的表结构:

users:

id | email

emails:

id | subject | body

user_emails:

user_id | email_id

这是非常简单的设计。但是,我需要为所有未在 user_emails 中关联的 users.id 选择第一个(最低的)emails.id。

举例说明:

users:

id | email
1 | email@domain.com
2 | test@lol.com
3 | user@test.com

emails:

id | subject | body
1 | sub1 | body1
2 | sub2 | body2

user_emails:

user_id | email_id
1 | 1
1 | 2
2 | 1

如数据所示:

  • 用户 1 已收到电子邮件 1 和 2,因此选择应排除 那个用户。
  • 用户 2 只收到邮件 1,所以应该选择用户 2 和电子邮件 2。
  • 用户 3 没有收到任何邮件,所以应该选择用户 3 和电子邮件 1。

我将在 PHP 中执行此操作,因此如果无法单独使用 mySQL 完成任何逻辑,则应使用 PHP 编写。

提前致谢

编辑:我可能应该提一下,会有数千个用户 ID 和数百个电子邮件 ID。发送所有这些电子邮件的脚本将每天运行一次。所以,这应该尽可能优化。

【问题讨论】:

  • 我有,但我对 mySQL 不是很有经验,这让我感到困惑。
  • 你的答案应该被张贴,然后你应该接受一个答案。 :-)
  • 请添加您的解决方案作为答案,而不是标记您的问题 [已解决]。您的答案(您可以在短暂的延迟后接受它是正确的)将帮助将来在搜索中找到此问题的其他人。 (FAQ 解释了如何回答您自己的问题。)谢谢。 :-)

标签: php mysql


【解决方案1】:

可以试试下面的:

SELECT * from users u 
LEFT JOIN users_emails e ON u.id=e.user_id 
LEFT OUTER JOIN emails m on m.id=1 
WHERE e.user_id is NULL

如果电子邮件中的 id 不需要为 1,则使用下面的查询。

SELECT * from users u 
LEFT JOIN users_emails e ON u.id=e.user_id 
LEFT OUTER join emails m on m.id=(SELECT id from emails order by id limit 1)   
WHERE e.user_id is NULL

【讨论】:

    【解决方案2】:

    我想到了一个更简单的解决方案来解决这一切。我在 users 表中添加了 lastSent 列。

    // Load all emails into an array. Use the id as the key.
    $sql = "SELECT * FROM emails";
    $query = mysql_query( $sql );
    while( $row = mysql_fetch_assoc( $query ) ) {
        $emails[ $row['id'] ] = $row;
    }
    
    // Load all users into an array.
    $sql = "SELECT id, email, lastSent FROM users";
    $query = mysql_query( $sql );
    while( $row = mysql_fetch_assoc( $query ) ) {
        $users = $row;
    }
    
    // Loop through each user and send next email from the list based on lastSent value.
    foreach ( $users as $user ) {
        $id = $user['lastSent'] + 1;
        $email = $user['email'];
        $subject = $emails[$id]['subject'];
        $body = $emails[$id]['body'];
        $send = mail($email, $subject, $body);
        if ( $send ) {
                // Update lastSent value.
            $sql = "UPDATE users SET lastSent='$id' WHERE id='" . $user['id'] . "'";
            mysql_query( $sql );
        }
    }
    

    【讨论】:

      【解决方案3】:

      试试下面的查询

      select t.id, min(t.q_id) from (SELECT u.id, e.id as q_id FROM users u CROSS JOIN emails e) as t where (t.id, t.q_id) not in (select * 来自 user_emails) 按 t.id 分组

      【讨论】: