2009-03-18 5 views
3

Disons que je les tableaux suivants:Comment sélectionner des valeurs de deux tables qui ne sont pas contenues dans la table de carte?

  • clients
  • Produits
  • CustomerProducts

Est-il possible que je peux faire une sélection des clients et des tables produits, où les valeurs ne sont PAS dans la table de carte? Fondamentalement j'ai besoin d'une liste assortie de clients et de produits qu'ils ne possèdent pas.

Autre détail: j'ai besoin de coupler un client par produit. Donc, si 5 clients n'ont pas de produit A, seul le premier client de la requête doit avoir le produit A. Les résultats ressemblent à ceci:

(Supposons que tous les clients possèdent le produit B, et que plus d'un client possède produits A, C et D)

  1. client 1, produit A
  2. client 2, produit C
  3. client 3, produit D

torsion finale: Je dois exécuter cette requête comme partie d'une instruction UPDATE dans SQL Sever. Donc, je dois prendre la valeur de la première ligne:

client 1, produit A

et mettre à jour la fiche client à quelque chose comme

UPDATE Customers 
SET Customers.UnownedProduct = ProductA 
WHERE Customers.CustomerID = Customer1ID 

Mais ce serait bien si je pouvais le faire processus complet, dans une instruction SQL. Donc, je lance la requête une fois, et il met à jour 1 client avec un produit qu'ils ne possèdent pas. J'espère que ce n'est pas trop déroutant pour vous! Merci d'avance! déclaration

+0

Et si vous avez deux clients et un seul client, que les deux ne possèdent pas? –

+0

Ensuite, la requête ne doit renvoyer qu'un seul enregistrement, avec le premier client. –

Répondre

3
WITH q AS 
     (
     SELECT c.*, p.id AS Unowned, 
       ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY c.id) AS rn 
     FROM Customers c 
     CROSS JOIN 
       Products p 
     LEFT JOIN 
       CustomerProducts cp 
     ON  cp.customer = c.id 
       AND cp.product = p.id 
     WHERE cp.customer IS NULL 
     ) 
UPDATE q 
SET  UnownedProduct = Unowned 
WHERE rn = 1 

UPDATE mettra à jour le premier client qui ne possède pas un produit.

Si vous souhaitez sélectionner la liste, vous aurez besoin:

SELECT * 
FROM (
     SELECT c.*, p.id AS Unowned, 
       ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY c.id) AS rn 
     FROM Customers c 
     CROSS JOIN 
       Products p 
     LEFT JOIN 
       CustomerProducts cp 
     ON  cp.customer = c.id 
       AND cp.product = p.id 
     WHERE cp.customer IS NULL 
    ) cpo 
WHERE rn = 1 
+0

Cela ne prend pas en compte l'autre tournure de l'OP? –

+0

Cela prend en compte les deux :) :) – Quassnoi

+0

+1. Je dois rattraper avec. –

0

Si vous mettez à jour un seul client à la fois, vous pourriez avoir besoin de se rappeler quels produits ont été attribués automatiquement (en CustomerProducts) ou ont un compteur à quelle fréquence un produit a été attribué automatiquement (en produits)

0

J'ai essayé dans l'oracle (espérons que cela fonctionne pour vous aussi)

UPDATE customers c 
    SET unownedProduct = 
     (SELECT MIN(productid) 
      FROM products 
      WHERE productid NOT IN (
       SELECT unownedProduct 
       FROM customers 
       WHERE unownedProduct IS NOT NULL) 
      AND productid NOT IN (
       SELECT productid 
       FROM customerProducts cp 
       WHERE cp.customerId = c.customerid) 
     ) 
WHERE customerId = 1 
0

Et si le cu stomer ne possède pas plus d'un produit? et comment allez-vous maintenir ce champ que les données changent? Je pense que vous devez vraiment réfléchir davantage à la structure de vos données car cela n'a aucun sens de stocker ces informations dans la table client.

Questions connexes