SQL XOR语法不起作用

时间:2014-12-03 15:30:06

标签: sql sql-server xor

我注意到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。

我再次检查了我的旧数学课程,但我不知道我在这里失踪了什么。

4 个答案:

答案 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'
                )
        )
    )