我注意到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。
我再次检查了我的旧数学课程,但我不知道我在这里失踪了什么。
答案 0 :(得分:2)
where
条件应用于单行的列,而不是一组行。
条件:
仅订购PA60或PA45但不同时订购两者的客户(NCLI)。
可以使用group by子句来解决:
select NCOM
from DETAIL
where NPRO IN ('PA60','PA45')
group by ncom
having count(distinct NPRO) = 1
distinct NPRO
仅在相同客户可以在同一产品的detail
表格中出现多次时才有必要。否则count(*)
也会这样做(但不同之处不会造成任何伤害)。
以上也将返回订购(仅)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
部分。
答案 1 :(得分:1)
那个大条件表达式只查看相同行中的数据,而不是每一行。
要执行您想要的操作,您需要将表与其自身进行比较(JOIN),以便可以将每一行与其他行进行比较。您可以使用排除连接执行此操作,其中您在表中查找某些条件的左连接,然后在where子句中通过将结果限制为字段的NULL记录来排除所有匹配从第二个表永远不应该是NULL。
将此问题应用于您的问题,然后最内部的选择查询应如下所示:
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查询而不是排除连接时,您有时也可以使用此功能,但我发现排除连接更容易使用。
除此之外,我们还应该将其他嵌套选择写为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
。
答案 2 :(得分:0)
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')
。
如果你想要的话,每一步都会产生错误的结果。
答案 3 :(得分:0)
有几种方法可以写这个,但这可能是你所拥有的最直接的。
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'
)
)
)