2010-01-19 6 views
2

Désolé, peut-être il est trivial, mais je ne peux pas trouver un moyen de le faire:sous-requête Mysql: Essayer d'obtenir la dernière commande d'un client

clients table

  • CUSTOMER_ID
  • customer_email
  • customer_newsletter (1 = yes/no = 0)

commandes de table

  • ORDER_ID
  • CUSTOMER_ID
  • ORDER_STATUS (1 = ok/0 = no_ok)

Chaque client peut avoir zéro, un ou plusieurs ordres.

Je suis en train de faire une requête pour obtenir tous les e-mails des personnes qui sont:

1/pas encore clients, ils ont jamais passé une commande, mais ils veulent recevoir ma newsletter

ou

2/déjà clients (une ou plusieurs commandes dans le tableau correspondant). Mais seulement si l'état de leur dernière commande est OK (je ne veux pas envoyer le bulletin d'information aux clients problématiques)

J'ai essayé plusieurs choses sur la base des sous-requêtes avec la fonction MAX, mais ne peut pas trouver le bon formulation

Un conseil? merci à l'avance

+0

Vous allez faciliter votre requête si vous incluez un champ de date dans la table ORDERS. – aiGuru

Répondre

0
SELECT customer_email 
FROM customers c 
WHERE customer_newsletter 
     AND COALESCE(
     (
     SELECT order_status 
     FROM orders o 
     WHERE o.customer_id = c.customer_id 
     ORDER BY 
       o.customer_id DESC, o.date_purchased DESC 
     LIMIT 1 
     ), 1) 

Créer un index sur orders (customer_id, date_purchased) pour que cela fonctionne rapidement. Cependant, cela fonctionnera même sans l'index.

Si vous voulez que les clients reçoivent des e-mails avec succès quels que soient leurs paramètres de bulletin, utilisez ceci:

SELECT customer_email 
FROM customers c 
WHERE COALESCE(
     (
     SELECT order_status 
     FROM orders o 
     WHERE o.customer_id = c.customer_id 
     ORDER BY 
       o.customer_id DESC, o.date_purchased DESC 
     LIMIT 1 
     ), customer_newsletter) 
+0

En fait, il y a aussi un champ date_purchased. Je pensais qu'il était possible d'obtenir le dernier avec quelque chose comme SELECT customers_id, orders_id, orders_status DE commandes OÙ orders_id IN ( \t SELECT max (orders_id) \t à partir des commandes \t OU orders_status = '1' \t GROUP BY customers_id ) Je n'ai pas la possibilité de définir ou de modifier l'index sur les tables. Je peux juste faire Sélectionne – aSa

+0

'@ aSa': mis à jour la réponse. Cela fonctionnera même sans l'index. – Quassnoi

+0

Parmi les clients avec des commandes OK, cela n'obtient que ceux qui veulent la newsletter. Cela semble raisonnable, mais le PO a seulement spécifié cette contrainte pour les clients sans commandes. –

0

Pour obtenir des clients sans commandes qui veulent votre bulletin, vous pouvez utiliser LEFT OUTER JOIN.

Exemple (non testé):

select c.* 
from customers c left outer join orders o 
on c.customer_id = o.customer_id 
where (o.customer_id is null) and customer_newsletter = 1 
order by c.customer_id 
1

1)

select * 
from customers c 
where customer_newsletter = 1 and 
not exists (select * from orders o where c.customer_id = o.customer_id) 

2)

select * 
from customers c 
where 1 = (select order_status from orders o1 
     where o1.customer_id = c.customer_id and 
      o1.order_id = (select max(order_id) 
          from orders o2 where o2.customer_id = c.customer_id) 
    ) 
1

Je pense En supposant que vous pouvez utiliser le plus grand numéro de commande comme la plus récente, devrait travail:

SELECT c.customer_email 
FROM customers c 
LEFT OUTER JOIN orders o ON o.customer_id = c.customer_id 
WHERE c.customer_newsletter = 1 AND o.customer_id IS NULL 
UNION 
SELECT c.customer_email 
FROM customers c 
WHERE customer_id IN 
    (SELECT customer_id FROM orders WHERE order_id IN 
    (SELECT MAX(order_id) FROM orders WHERE order_status = 1 GROUP BY customer_id) 
) 
Questions connexes