Northwind数据库查询匹配CENTC客户全部购品的客户名称SQL问题
Northwind数据库通用查询方案:获取购买指定客户全部产品的客户名称
需求说明
基于Northwind数据库,查询所有购买过CustomerID为CENTC的客户所购全部产品的客户名称,要求方案具备通用性,更换目标客户ID时无需手动修改硬编码参数。
原有实现问题
现有硬编码方案将CENTC购买的产品ID、求和值固定写入SQL,仅能适配单一场景,且通过sum(ProductID)做匹配的逻辑存在漏洞:不同产品ID的组合可能出现相同求和结果,会导致查询结果不准确。
通用实现方案
核心逻辑
- 动态查询目标客户购买的所有去重产品ID,同时统计其购买的产品总数量
- 对每个客户,统计其购买的、属于目标客户产品集合的去重产品数量
- 匹配两者数量相等的客户,即为买齐目标客户所有产品的用户
通用SQL代码
SELECT DISTINCT c.CompanyName FROM Customers c JOIN Orders o ON c.CustomerID = o.CustomerID JOIN [Order Details] od ON o.OrderID = od.OrderID WHERE od.ProductID IN ( -- 子查询动态获取目标客户购买的所有产品ID SELECT DISTINCT od_sub.ProductID FROM Customers c_sub JOIN Orders o_sub ON c_sub.CustomerID = o_sub.CustomerID JOIN [Order Details] od_sub ON o_sub.OrderID = od_sub.OrderID WHERE c_sub.CustomerID = 'CENTC' ) GROUP BY c.CustomerID, c.CompanyName -- 去重后的匹配产品数等于目标客户购买的产品总数,即买齐所有产品 HAVING COUNT(DISTINCT od.ProductID) = ( -- 子查询动态获取目标客户购买的产品总数量 SELECT COUNT(DISTINCT od_sub.ProductID) FROM Customers c_sub JOIN Orders o_sub ON c_sub.CustomerID = o_sub.CustomerID JOIN [Order Details] od_sub ON o_sub.OrderID = od_sub.OrderID WHERE c_sub.CustomerID = 'CENTC' )
方案优势
- 通用性强:仅需修改子查询中的客户ID值,即可适配任意目标客户的同类查询需求
- 逻辑严谨:通过去重计数匹配替代求和判断,避免ID数值巧合导致的查询错误
- 无需前置计算:所有目标值通过子查询动态获取,不需要提前查询产品ID手动填入SQL
可选优化(高频查询场景)
如果需要频繁进行同类查询,可以将SQL封装为存储过程,传入目标客户ID作为参数,进一步提升易用性:
CREATE PROCEDURE GetCustomersBoughtAllProductsOfTarget @TargetCustomerID NCHAR(5) AS BEGIN SELECT DISTINCT c.CompanyName FROM Customers c JOIN Orders o ON c.CustomerID = o.CustomerID JOIN [Order Details] od ON o.OrderID = od.OrderID WHERE od.ProductID IN ( SELECT DISTINCT od_sub.ProductID FROM Customers c_sub JOIN Orders o_sub ON c_sub.CustomerID = o_sub.CustomerID JOIN [Order Details] od_sub ON o_sub.OrderID = od_sub.OrderID WHERE c_sub.CustomerID = @TargetCustomerID ) GROUP BY c.CustomerID, c.CompanyName HAVING COUNT(DISTINCT od.ProductID) = ( SELECT COUNT(DISTINCT od_sub.ProductID) FROM Customers c_sub JOIN Orders o_sub ON c_sub.CustomerID = o_sub.CustomerID JOIN [Order Details] od_sub ON o_sub.OrderID = od_sub.OrderID WHERE c_sub.CustomerID = @TargetCustomerID ) END -- 调用示例:EXEC GetCustomersBoughtAllProductsOfTarget 'CENTC'
内容的提问来源于stack exchange,提问作者Frontmaniaac
相关产品推荐
相关产品推荐

