Como selecionar valores de duas tabelas que não estão contidas na tabela de mapa?
-
20-08-2019 - |
Pergunta
Vamos dizer que eu tenho as seguintes tabelas:
- Clientes
- Produtos
- CustomerProducts
Existe uma maneira que eu possa fazer uma escolha dos clientes e produtos mesas, onde os valores não estão na tabela de mapa? Basicamente, eu preciso de uma lista correspondente de clientes e produtos que não possuem.
Outra reviravolta: Eu preciso emparelhar um cliente por produto. Então Se 5 clientes não têm o produto A, apenas o primeiro cliente na consulta deve ter o produto A. Assim, os resultados seria algo parecido com isto:
(Suponha que todos os clientes próprio produto B, E, mais do que um cliente possui produtos A, C, e D)
- Cliente 1, Product A
- Cliente 2, Product C
- Cliente 3, o Produto D
toque final: eu preciso para executar essa consulta como parte de uma instrução UPDATE no SQL Sever. Então eu preciso tomar o valor da primeira linha:
Cliente 1, Product A
e atualizar o registro do cliente para algo como
UPDATE Customers
SET Customers.UnownedProduct = ProductA
WHERE Customers.CustomerID = Customer1ID
Mas seria bom se eu poderia fazer todo este processo, em uma instrução SQL. Então eu executar a consulta uma vez, e ele atualiza 1 cliente com um produto que eles não possuem. Esperança que não é muito confuso para você! Agradecemos antecipadamente!
Solução
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
declaração UPDATE
irá atualizar o início cliente que não possua um determinado produto.
Se você quiser selecionar a lista, você vai precisar:
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
Outras dicas
Se você atualizar apenas um cliente de uma vez, você pode precisar de se lembrar que produtos foram atribuídos automaticamente (em CustomerProducts) ou ter um contador de quantas vezes um produto foi atribuído automaticamente (em produtos)
Eu tentei isso no Oracle (espero que funcione para você também)
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
E se o cliente não possuir mais de um produto? e como você está indo para manter este campo como as alterações de dados? I thinkyou realmente precisa fazer mais algumas reflexões sobre sua estrutura de dados, uma vez que não faz sentido para armazenar essas informações na tabela de clientes.