2012-06-21 2 views
5

Voici ma structure de table:mySQL complexe requête SELECT?

users: 

id | email 

emails: 

id | subject | body 

user_emails: 

user_id | email_id 

Il est conception très simple. Cependant, j'ai besoin de sélectionner le premier (le plus bas) email.id pour tous les users.id qui ne sont pas associés dans user_emails.

À titre d'illustration:

users: 

id | email 
1 | [email protected] 
2 | [email protected] 
3 | [email protected] 

emails: 

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

user_emails: 

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

Comme les données montrent:

  • utilisateur 1 a reçu email 1 et 2 déjà si la sélection doit exclure cet utilisateur.
  • utilisateur 2 n'a reçu email 1, il devrait donc sélectionner l'utilisateur 2 et email 2.
  • Utilisateur 3 n'a pas reçu d'e-mails, il doit sélectionner l'utilisateur 3 et email 1.

Je vais le faire en PHP donc toute logique devrait être écrit en PHP si cela ne peut être fait avec mySQL seul.

Merci à l'avance

EDIT: Je dois mentionner sans doute qu'il y aura des milliers d'utilisateurs ID de centaines et de courrier électronique id. Le script qui enverra tous ces emails sera exécuté une fois par jour. Donc, cela devrait être aussi optimisé que possible.

+2

Lire sur LEFT JOIN. –

+0

J'ai mais je ne suis pas très expérimenté avec mySQL et cela devient confus pour moi. –

+1

Votre réponse devrait être affichée telle, et vous devriez alors accepter une réponse. :-) –

Répondre

0

J'ai pensé à une solution beaucoup plus simple à tout cela. J'ai ajouté une colonne lastSent à la table des utilisateurs.

// 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); 
    } 
} 
2

pourrait essayer le ci-dessous:

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 

Ou utilisez le ci-dessous si l'identifiant dans les messages électroniques ne sont pas nécessaires pour être 1 ci-dessus requête.

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 
0

Donnez un essai avec la requête ci-dessous

select t.id, min (t.q_id) de (SELECT u.id, e.id comme q_id FROM utilisateurs u CROSS JOIN e-mails e) comme t où (t.id, t.q_id) n'est pas dans (sélectionnez * from user_emails) groupe par t.id