Question

Disons que j'ai les tables suivantes:

  • clients
  • Produits
  • CustomerProducts

Puis-je effectuer une sélection dans les tables Clients et Produits, où les valeurs ne sont PAS dans la table de cartes? En gros, j'ai besoin d'une liste correspondante de clients et de produits qu'ils ne possèdent pas.

Autre particularité: je dois associer un client par produit. Donc, si 5 clients n'ont pas le 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 les produits A, C et D)

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

Final twist: Je dois exécuter cette requête dans le cadre d’une instruction UPDATE dans SQL Server. J'ai donc besoin de prendre la valeur de la première ligne:

Client 1, Produit A

et mettez à jour l'enregistrement du client pour obtenir quelque chose comme

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

Mais ce serait bien si je pouvais faire tout ce processus, en une seule 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!

Était-ce utile?

La solution

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
L’instruction

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

Si vous souhaitez sélectionner la liste, vous avez besoin des éléments suivants:

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

Autres conseils

Si vous ne mettez à jour qu'un client à la fois, vous devrez peut-être mémoriser les produits attribués automatiquement (dans CustomerProducts) ou disposer d'un compteur indiquant la fréquence à laquelle un produit a été affecté automatiquement (dans Produits)

J'ai essayé ceci en oracle (j'espère que ça marche 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

Que se passe-t-il si le client ne possède pas plus d'un produit? et comment allez-vous gérer ce champ à mesure que les données changent? Je pense que vous devez vraiment réfléchir davantage à votre structure de données car il n’a aucun sens de stocker ces informations dans la table des clients.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top