[英]SQL XOR syntax isn't working
我注意到SQL SERVER EXPRESS中没有XOR函数,因此我尝试使用旧方法。
select NCLI
from CLIENT
where NCLI in (select NCLI
from COMMANDE
where NCOM in (select NCOM
from DETAIL
where ((NPRO = 'PA60' and NPRO <> 'PA45')
or (NPRO <> 'PA60' and NPRO = 'PA45'))))
现在,我不是数学专家,但据我所知,这应该给我提供仅订购PA60或PA45而不订购两者的客户数量(NCLI)。
结果是,它同时也为同时订购两者的人员提供了NCLI。
我再次检查了我的旧数学课程,但是我不知道我在这里缺少什么。
甲where
条件被施加到单个行的列,而不是一组行。
条件:
可以使用group by子句解决:
select NCOM
from DETAIL
where NPRO IN ('PA60','PA45')
group by ncom
having count(distinct NPRO) = 1
仅当同一客户可以在同一产品的detail
表中出现多次时,才需要使用唯一的distinct NPRO
。 否则, count(*)
也将起作用(但在此对distinct不会造成任何损害)。
上面的内容还将返回仅订购PA60和其他产品的客户。 如果您还想排除那些商品,则需要添加其他条件,以仅包括订购商品数量等于商品数量的商品。
select NCOM
from DETAIL
where NPRO IN ('PA60','PA45')
group by ncom
having count(NPRO) = 1
and count(NPRO) = (select count(*)
from DETAIL d2
where d2.ncom = detail.ncom)
第二个条件也可以放在where
部分。
这个大的条件表达式只查看同一行中的数据,而不是每一行中的数据。
要执行所需的操作,您需要将表与其自身进行比较(JOIN),以便可以将每一行与其他行进行比较。 您可以使用排除联接来执行此操作,在该联接中您对表进行了左联接以寻找某种条件,然后在where子句中通过将结果限制为NULL记录来限制第二个表中某个字段的记录,从而排除所有匹配项为NULL。
将此应用于您的问题,然后最里面的select查询应如下所示:
select d1.NCOM
from DETAIL d1
left join DETAIL d2 on d2.NCOM = d1.NCOM and d2.NPRO <> d1.NPRO and d2.NPRO IN ('PA60', 'PA45')
where d1.NPRO IN ('PA60', 'PA45') and d2.NCOM IS NULL
有时您可以通过NOT EXISTS查询而不是排除联接来使它更好地执行,这一点也不值钱,但是我发现排除联接更容易使用。
有了这一点,我们还应该将其他嵌套的select编写为JOIN:
select cl.NCLI
from DETAIL d1
left join DETAIL d2 on d2.NCOM = d1.NCOM and d2.NPRO <> d1.NPRO and d2.NPRO IN ('PA60', 'PA45')
inner join COMMANDE cm on cm.NCOM = d1.NCOM
inner join CLIENT cl on cl.NCLI = cm.NCLI
where d1.NPRO IN ('PA60', 'PA45') and d2.NCOM IS NULL
根据表中的关系,您可能还需要为此添加一个distinct
的内容。
where NCOM in
(select NCOM from DETAIL where (
(NPRO = 'PA60' and NPRO <> 'PA45')
or (NPRO <> 'PA60' and NPRO = 'PA45')
)
您应该注意到, 为每行都处理了此WHERE
,这意味着您在子句中进行了多余的检查。
每当NPRO
值保存PA60
,很明显它不会在同一行中保存任何其他值(因为它不是ARRAY
)。
相同的规则适用于第二个条件。
你WHERE
其实看起来像
WHERE NCOM IN ( SELECT NCOM FROM DETAIL WHERE NPRO = 'PA60' OR NPRO = 'PA45' )
所以这个子查询让你NCOM
所有NPRO
是IN ('PA60','PA45')
而且每走一步,对于您想要的情况都会产生错误的结果。
有多种写方法,但这可能是您所掌握的最简单的方法。
SELECT NCLI
FROM CLIENT
WHERE NCLI IN (
SELECT NCLI
FROM COMMANDE
WHERE NCOM IN (
SELECT NCOM
FROM DETAIL
WHERE NPRO IN ('PA60', 'PA45')
AND NCOM NOT IN (
SELECT NCOM
FROM DETAIL
WHERE NPRO = 'PA60'
INTERSECT
SELECT NCOM
FROM DETAIL
WHERE NPRO = 'PA45'
)
)
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.