You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

获取未被各客户购买的产品对应的客户名与产品名

解决SQL查询客户未购买产品的问题

原始表结构及数据

以下是测试用的表定义和数据插入语句:

declare @customer table(CId int identity,Cname varchar(10))
insert into @customer values('A'),('B')
--select * from @customer

declare @Product table(PId int identity,Pname varchar(10))
insert into @Product values('P1'),('P2'),('P3'),('P4')
--select * from @Product

declare @CustomerProduct table(CPId int identity,Cid int, Pid int)
insert into @CustomerProduct values(1,1),(1,2),(2,1),(2,4)

需求及期望输出

需要获取每个客户未购买的产品对应的客户名称(Cname)和产品名称(Pname),正确的期望输出如下:

declare @outputtable table (Cname varchar(10), Pname varchar(10))
insert into @outputtable values('A','P3'),('A','P4'),('B','P2'),('B','P3')
select * from @outputtable

注:原需求中的期望输出存在重复记录,此处已修正为正确的无重复结果

用户尝试的错误查询

用户使用左连接但仅得到已购买的产品记录,查询语句如下:

Select P.Pname,C.Cname from @Product p
left join @CustomerProduct cp on cp.Pid=p.pId
Left Join @customer c  on cp.Cid=c.CId
where c.CId=cp.Cid

原查询的问题在于:where c.CId=cp.Cid条件过滤掉了左连接中不匹配的记录,等价于将左连接转为内连接,因此只能获取到已有购买记录的产品。

正确的SQL查询语句

方法1:交叉连接+EXCEPT排除已购买组合

先生成所有客户与产品的可能组合,再排除已存在于购买表中的组合:

SELECT c.Cname, p.Pname
FROM @customer c
CROSS JOIN @Product p
EXCEPT
SELECT c.Cname, p.Pname
FROM @customer c
JOIN @CustomerProduct cp ON c.CId = cp.Cid
JOIN @Product p ON cp.Pid = p.PId

方法2:交叉连接+左连接筛选未匹配记录

通过交叉连接生成全量组合,左连接购买表后筛选无匹配记录的行:

SELECT c.Cname, p.Pname
FROM @customer c
CROSS JOIN @Product p
LEFT JOIN @CustomerProduct cp 
  ON c.CId = cp.Cid AND p.PId = cp.Pid
WHERE cp.CPId IS NULL

两种方法都能得到符合需求的结果,即每个客户未购买的产品列表。

内容的提问来源于stack exchange,提问作者Rahul Aggarwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:15:13