什么t-sql查询将选择具有两个特定产品的客户

时间:2015-04-01 23:08:28

标签: sql-server tsql combinations

我有一张带有custid和prodid的产品表。

我需要查询表格以确定有多少客户拥有特定的产品组合:

  • 至少1个产品编号1
  • (2,3,4,5)中的至少一种产品

然后我需要能够列出该类别的客户。

这个问题被问到here但是当我尝试推荐的解决方案时,我收到了错误:

  

' USING'附近的语法不正确。

代码:

SELECT 
    COUNT(DISTINCT t1.custid) AS user_count
FROM 
    custrate t1
JOIN 
    custrate t2 USING (custid)
WHERE 
    t1.rgid = 333 
    AND t2.rgid in (321, 325, 329, 345, 360, 364)

提前致谢。

1 个答案:

答案 0 :(得分:2)

让我们从逻辑上理解这一点。凭借较少的经验,我的第一直觉就是加入具有特定标准的产品。问题是我最终得到了多条记录,因此我需要汇总给客户:

Select c.CustomerId
From Customer c
Join Product p on p.CustomerId = c.CustomerId
Where p.ProductId in (2, 3, 4, 5)
or p.ProductId = 1

显然这是错误的,因为更糟糕的情况是它为我们提供了5条特定客户加入最多5个匹配产品的记录。如果只有满足BOTH条件才能获得单一记录,我们必须考虑如何“查看记录”。 “查看记录”有三种常用方法:

  1. 子查询,可以选择,也可以使用inexists子句,或者偶尔作为嵌套连接使用。{/ p>

  2. 聚合查询。这有时需要一点创造力和解决问题。

  3. 窗口函数,例如MAX() OVER (PARTITION BY...)

  4. 可能与上述相结合将是CASE WHEN条件。

    如果你学习了上述所有技巧,你将拥有一个更大的心理工具带来开始创造性地解决这些问题。这个答案有点宽泛,可以展示所有这些的例子,所以我只会展示一个解决你的问题。

    EXISTS Subquery

    带有EXISTS的子查询检查子查询是否返回至少一条记录,如果找到任何记录,则EXISTS返回true。因为实际上没有使用结果,并且我们只关心是否至少有一条记录,所以在子查询的select中返回的内容并不重要,所以我们只返回1

    Select c.CustomerId
    From Customer c
    Join Product p on p.CustomerId = c.CustomerId
    Where p.ProductId = 1
    

    以上单独返回不超过一条记录,并且仅当客户具有ID = 1的相关产品时。下面添加额外标准以消除其中一个记录中没有至少一个记录的记录现有产品:

    Select c.CustomerId
    From Customer c
    Join Product p on p.CustomerId = c.CustomerId
    Where p.ProductId = 1
      AND EXISTS
       (Select 1 From Product p2
        Where p2.ProductId in (2, 3, 4, 5)
          AND p2.CustomerId = c.CustomerId )
    

    这是最终解决方案。请注意,重要的是我们只能在子查询中找到相关记录。为了实现这一点,从外部查询中的一个或多个条件与内部查询匹配是很常见的。在这种情况下,我们从外部查询c.CustomerIDp2.CustomerId缩小内部查询的结果。

    已更新自我加入:

    SELECT DISTINCT p1.CustomerId
      FROM Products p1
      JOIN Products p2 on p1.CustomerId = p2.CustomerId
     WHERE p1.ProductId = 1 
       AND p2.ProductId in (2, 3, 4, 5)