日期:2014-05-17  浏览次数:20419 次

求高手解答一个查询的逻辑思路
今天在网上下了一个SQL查询练习题,其中有这样一个查询。 表OrderItem(顾客号,商品号,数量。日期) 要求如下:
/* 检索这样的顾客号,他们至少订购了顾客号为“0002”所订购的所有商品 (除法)*/

给出的答案是:
SQL code
select distinct 顾客号 from OrderItem X where not exists 
(select * from OrderItem Y where 顾客号='0002' and not exists
(select * from OrderItem Z where Z.顾客号=X.顾客号 and Z.商品号=Y.商品号))




在这里请教下各位高手,这个答案的逻辑是怎么样的。不甚感激啊!

------解决方案--------------------
子查询的分析方式一般是从内向外:
SQL code

select 商品号 from OrderItem Z where Z.顾客号=X.顾客号

------解决方案--------------------
SQL code

select distinct 顾客号 --找出不同的顾客号
from OrderItem X  --从 OrderItem 表,别名X中
where not exists -- 筛选X的条件是不存在以下情况 
(select * from OrderItem Y where 顾客号='0002' --商品在002那
and not exists (select * from OrderItem Z 
where Z.顾客号=X.顾客号 and Z.商品号=Y.商品号))--且不再自己这
-- 即 筛选出所有  不存在(某商品002有而“我”没有) 中的“我”
--换一说法:如果 (某商品002有而“我”没有)这一情况不存在,那我就是符合条件的顾客

------解决方案--------------------
SQL code
--整句查询
select distinct 顾客号 from OrderItem X where not exists 
(select * from OrderItem Y where 顾客号='0002' and not exists
(select * from OrderItem Z where Z.顾客号=X.顾客号 and Z.商品号=Y.商品号))
--先考虑下以下查询
select * from OrderItem Y where 顾客号='0002' and not exists
(select * from OrderItem Z where Z.顾客号=X.顾客号 and Z.商品号=Y.商品号))
--select * from OrderItem Y where 顾客号='0002'  为0002顾客的全部商品
--加上and not exists (select * from OrderItem Z where Z.顾客号=X.顾客号 and Z.商品号=Y.商品号))
--意思为0002顾客的所有商品中不包含X顾客商品的记录,如果这样的记录存在,
--证明0002顾客的商品中有x顾客商品中未有的
--再考虑
select distinct 顾客号 from OrderItem X
--对x表的每一条记录,都执行上面的查询,假设第一条记录的顾客号为'0003'
--执行
select * from OrderItem Y where 顾客号='0002' and not exists
(select * from OrderItem Z where Z.顾客号='0003' and Z.商品号=Y.商品号))
--如果存在记录,说明顾客'0002'的商品中含有顾客'0003'未订购的商品
--反过来,只有以上查询不存在记录,才能说明'0003'的商品已包含顾客'0002'的全部商品
--所以加上not exists 变为
not exists(
select * from OrderItem Y where 顾客号='0002' and not exists
(select * from OrderItem Z where Z.顾客号='0003' and Z.商品号=Y.商品号)))
--再加上select * from orderitem X 就是全部整条查询的内容

------解决方案--------------------
为了方便理解,建了个 OrderItem数据表
OrderItem
顾客号 商品号
0001 01
0001 02
0001 03
0002 01
0002 02
0003 01
0003 04
0004 04
0004 05 

里面的 exists 语句可以写成
SQL code
select * from OrderItem Y where 顾客号='0002' and not exists
(select * from OrderItem Z where Z.顾客号=@顾客号 and Z.商品号=Y.商品号)