t-sql 查询 select 有两种特定产品的客户
what t-sql query would select customers with two specific products
我有一个产品 table 含有 custid 和 prodid。
我需要查询 table 以确定有多少客户拥有特定产品组合:
- 至少 1 个产品编号 1
- 至少 1 个产品在 (2, 3, 4, 5)
然后我需要能够列出该类别中的客户。
有人问过这个问题 here 但是当我尝试推荐的解决方案时出现错误:
Incorrect syntax near '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)
提前致谢。
让我们从逻辑上分析一下。由于经验较少,我的第一直觉是加入具有特定标准的产品。问题是我最终会得到多个记录,所以我需要汇总到一个客户:
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 个匹配的产品。如果目标是在满足两个条件的情况下获得一条记录,我们必须考虑如何"look across records"。 "looking across records" 的三种常用方法:
子查询,可以在 select 中,也可以在 where 条件中使用 in
或 exists
子句,或者偶尔作为嵌套连接.
聚合查询。这有时需要一点创造力和解决问题的能力。
一个window函数如MAX() OVER (PARTITION BY...)
可能与上述组合是 CASE WHEN
条件。
如果您学会了上述所有技巧,您将拥有更大的思维工具带,可以开始创造性地解决这些问题。这个答案有点宽泛,无法尝试展示所有这些示例,所以我只展示一个解决您问题的方法。
EXISTS 子查询
带有 EXISTS
的子查询检查是否至少有一条记录是从子查询中 return 编辑的,如果任何记录是 EXISTS
returns true成立。因为实际上并没有使用结果,我们只关心是否至少有一条记录,所以在子查询的 select
中 return 是什么并不重要,所以我们只 return 1
:
Select c.CustomerId
From Customer c
Join Product p on p.CustomerId = c.CustomerId
Where p.ProductId = 1
以上仅 return 不超过一条记录,并且仅当客户有 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.CustomerID
和 p2.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)
我有一个产品 table 含有 custid 和 prodid。
我需要查询 table 以确定有多少客户拥有特定产品组合:
- 至少 1 个产品编号 1
- 至少 1 个产品在 (2, 3, 4, 5)
然后我需要能够列出该类别中的客户。
有人问过这个问题 here 但是当我尝试推荐的解决方案时出现错误:
Incorrect syntax near '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)
提前致谢。
让我们从逻辑上分析一下。由于经验较少,我的第一直觉是加入具有特定标准的产品。问题是我最终会得到多个记录,所以我需要汇总到一个客户:
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 个匹配的产品。如果目标是在满足两个条件的情况下获得一条记录,我们必须考虑如何"look across records"。 "looking across records" 的三种常用方法:
子查询,可以在 select 中,也可以在 where 条件中使用
in
或exists
子句,或者偶尔作为嵌套连接.聚合查询。这有时需要一点创造力和解决问题的能力。
一个window函数如
MAX() OVER (PARTITION BY...)
可能与上述组合是 CASE WHEN
条件。
如果您学会了上述所有技巧,您将拥有更大的思维工具带,可以开始创造性地解决这些问题。这个答案有点宽泛,无法尝试展示所有这些示例,所以我只展示一个解决您问题的方法。
EXISTS 子查询
带有 EXISTS
的子查询检查是否至少有一条记录是从子查询中 return 编辑的,如果任何记录是 EXISTS
returns true成立。因为实际上并没有使用结果,我们只关心是否至少有一条记录,所以在子查询的 select
中 return 是什么并不重要,所以我们只 return 1
:
Select c.CustomerId
From Customer c
Join Product p on p.CustomerId = c.CustomerId
Where p.ProductId = 1
以上仅 return 不超过一条记录,并且仅当客户有 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.CustomerID
和 p2.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)