Как выбрать значения из двух таблиц, которые не содержатся в таблице карты? - PullRequest
3 голосов
/ 18 марта 2009

Допустим, у меня есть следующие таблицы:

  • Клиенты
  • Продукты
  • CustomerProducts

Есть ли способ сделать выбор из таблиц "Клиенты и продукты", где значения НЕ находятся в таблице карт? В основном мне нужен соответствующий список клиентов и продуктов, которые им НЕ принадлежат.

Еще один поворот: мне нужно объединить одного покупателя для каждого продукта. Таким образом, если у 5 клиентов нет Продукта A, только у первого клиента в запросе должен быть Продукт A. Таким образом, результаты будут выглядеть примерно так:

(Предположим, что все клиенты владеют продуктом B, а продукты A, C и D принадлежат более чем одному клиенту)

  1. Заказчик 1, Продукт A
  2. Заказчик 2, продукт C
  3. Заказчик 3, продукт D

Последний поворот: мне нужно выполнить этот запрос как часть оператора UPDATE в SQL Server. Поэтому мне нужно взять значение из первого ряда:

Заказчик 1, Продукт A

и обновите запись о клиенте до

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

Но было бы неплохо, если бы я мог выполнить весь этот процесс одним оператором SQL. Поэтому я запускаю запрос один раз, и он обновляет 1 клиента продуктом, который ему не принадлежит. Надеюсь, это вас не смущает! Заранее спасибо!

Ответы [ 4 ]

3 голосов
/ 18 марта 2009
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 оператор обновит первого клиента, который не владеет определенным продуктом.

Если вы хотите выбрать список, вам понадобится:

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 голосов
/ 18 марта 2009

Что делать, если клиент не владеет более чем одним продуктом? и как вы собираетесь поддерживать это поле при изменении данных? Я думаю, вам действительно нужно больше подумать о структуре данных, так как нет смысла хранить эту информацию в таблице клиентов.

0 голосов
/ 18 марта 2009

Я попробовал это в оракуле (надеюсь, это работает и для вас)

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 голосов
/ 18 марта 2009

Если вы обновляете только одного покупателя за один раз, вам может потребоваться запомнить, какие продукты были назначены автоматически (в CustomerProducts), или иметь счетчик того, как часто продукт назначался автоматически (в Products)

...