【问题标题】:How to select values from two tables that are not contained in the map table?如何从两个表中选择不包含在映射表中的值?
【发布时间】:2009-03-18 15:12:24
【问题描述】:

假设我有以下表格:

  • 客户
  • 产品
  • 客户产品

有没有一种方法可以从客户和产品表中进行选择,其中值不在映射表中?基本上我需要一个匹配的客户和他们不拥有的产品列表。

另一个转折点:我需要为每个产品配对一个客户。因此,如果 5 个客户没有产品 A,则只有查询中的第一个客户应该有产品 A。所以结果看起来像这样:

(假设所有客户都拥有产品 B,并且不止一个客户拥有产品 A、C 和 D)

  1. 客户 1,产品 A
  2. 客户 2,产品 C
  3. 客户 3,产品 D

最后的转折:我需要将此查询作为 SQL Sever 中 UPDATE 语句的一部分运行。所以我需要从第一行取值:

客户 1,产品 A

并将客户记录更新为类似

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

但如果我能在一个 SQL 语句中完成整个过程,那就太好了。所以我运行了一次查询,它用他们不拥有的产品更新了 1 个客户。 希望这不会让您感到困惑!提前致谢!

【问题讨论】:

  • 如果您有两个客户,只有一个产品,但他们都不拥有?
  • 那么查询应该只返回一条记录,第一个客户。

标签: sql sql-server stored-procedures subquery nested-queries


【解决方案1】:
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

【讨论】:

  • 这没有考虑到 OP 的另一个和最后的转折?!
  • 这两者都考虑到了:)
【解决方案2】:

如果您一次只更新一个客户,您可能需要记住自动分配的产品(在 CustomerProducts 中)或有一个计数器自动分配产品的频率(在 Products 中)

【讨论】:

    【解决方案3】:

    我在 oracle 中试过这个(希望它也适用于你)

    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
    

    【讨论】:

      【解决方案4】:

      如果客户拥有的产品不超过一种怎么办?随着数据的变化,你将如何维护这个字段?我认为您确实需要更多地考虑您的数据结构,因为将这些信息存储在客户表中是没有意义的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-25
        • 1970-01-01
        • 2012-02-11
        • 1970-01-01
        • 2016-03-19
        相关资源
        最近更新 更多