WHERE <Cond> OR <Cond> 但不是两者

WHERE <Cond> OR <Cond> but not both

我正在尝试查找适用于以下设备的设备:

但我想排除所有两个条目都为真的结果,直到现在我才设法做到这一点。无论我尝试什么,当 1 和 2 为真时,它就会像假的那样运行...

SELECT DISTINCT 
    Devices.DeviceName
FROM
    Devices
LEFT OUTER JOIN 
    CustInv_ObjType_6121 BCMModulesVersions ON Devices.DeviceID = BCMModulesVersions.DeviceID
LEFT OUTER JOIN 
    InventoryIntegrationData InventoryUpdate ON Devices.DeviceID = InventoryUpdate.DeviceID
WHERE  
    ((BCMModulesVersions.InstanceName NOT IN ('PatchManagementPremium', 'RemoteControl'))
    AND (InventoryUpdate.IntegrationDate IS NOT NULL)
    AND Devices.TopologyType IN ('_DB_DEVTYPE_CLIENT_', '_DB_DEVTYPE_RELAY_'))
ORDER BY 
    Devices.DeviceName ASC; 

更清楚一点:我支持一个可以加载或不加载多个模块的应用程序。此信息存储在数据库中。加载模块后,您会在该设备的实例名称列中找到它的名称(remotecontrol、patchmanagementpremium 等)。

我想列出所有没有加载模块remotecontrol,或者没有加载模块补丁,或者两个模块都没有加载的设备。

如果两个条目都已加载,则设备名称不应出现在查询的输出中。

如果我理解正确的话,你基本上可以这样做:

WHERE NOT(1 AND 2) AND (1 OR 2)

将过滤器移动到 HAVING 子句并进行条件计数

这是一种方法

SELECT Devices.DeviceName
FROM   Devices
       JOIN CustInv_ObjType_6121 BCMModulesVersions
         ON Devices.DeviceID = BCMModulesVersions.DeviceID
       JOIN InventoryIntegrationData InventoryUpdate
         ON Devices.DeviceID = InventoryUpdate.DeviceID
WHERE  ( InventoryUpdate.IntegrationDate IS NOT NULL )
       AND Devices.TopologyType IN ( '_DB_DEVTYPE_CLIENT_', '_DB_DEVTYPE_RELAY_' )
GROUP  BY Devices.DeviceName
HAVING Count(CASE
               WHEN BCMModulesVersions.InstanceName IN ( 'PatchManagementPremium', 'RemoteControl' ) THEN 1
             END) = 0 

我想你可以在这里使用 NOT EXISTS。

SELECT DISTINCT
        Devices.DeviceName
FROM    Devices
        INNER JOIN InventoryIntegrationData InventoryUpdate ON Devices.DeviceID = InventoryUpdate.DeviceID
WHERE   InventoryUpdate.IntegrationDate IS NOT NULL
        AND Devices.TopologyType IN ('_DB_DEVTYPE_CLIENT_','_DB_DEVTYPE_RELAY_')
        AND NOT EXISTS ( SELECT 1
                         FROM   CustInv_ObjType_6121 BCMModulesVersions
                         WHERE  Devices.DeviceID = BCMModulesVersions.DeviceID
                                AND BCMModulesVersions.InstanceName IN ('PatchManagementPremium','RemoteControl'))
ORDER BY Devices.DeviceName ASC; 

如果您只想在两个值都存在时排除,您可以使用。

SELECT DISTINCT
        Devices.DeviceName
FROM    Devices
        JOIN InventoryIntegrationData InventoryUpdate ON Devices.DeviceID = InventoryUpdate.DeviceID
WHERE   InventoryUpdate.IntegrationDate IS NOT NULL
        AND Devices.TopologyType IN ('_DB_DEVTYPE_CLIENT_','_DB_DEVTYPE_RELAY_')
        AND 2 > ( SELECT COUNT(DISTINCT BCMModulesVersions.InstanceName)
                         FROM   CustInv_ObjType_6121 BCMModulesVersions
                         WHERE  Devices.DeviceID = BCMModulesVersions.DeviceID
                                AND BCMModulesVersions.InstanceName IN ('PatchManagementPremium','RemoteControl'))
ORDER BY Devices.DeviceName ASC; 

我认为你是说两个案例中的一个或两个都缺失(所以它们都存在被排除)

SELECT DISTINCT 
    Devices.DeviceName
FROM
    Devices
LEFT OUTER JOIN 
    CustInv_ObjType_6121 BCMModulesVersions ON Devices.DeviceID = BCMModulesVersions.DeviceID
LEFT OUTER JOIN 
    InventoryIntegrationData InventoryUpdate ON Devices.DeviceID = InventoryUpdate.DeviceID
WHERE  

    (NOT EXISTS (SELECT 0 FROM CustInv_ObjType_6121 X WHERE X.InstanceName IN('RemoteControl'))
        OR
     NOT EXISTS (SELECT 0 FROM CustInv_ObjType_6121 Y WHERE Y.InstanceName IN('PatchManagementPremium'))
    )
    AND (InventoryUpdate.IntegrationDate IS NOT NULL)
    AND Devices.TopologyType IN ('_DB_DEVTYPE_CLIENT_', '_DB_DEVTYPE_RELAY_')
ORDER BY 
    Devices.DeviceName ASC; 

感谢 JamieD77,我找到了解决方案! :)

SELECT DISTINCT
        Devices.DeviceName
FROM    Devices
        JOIN InventoryIntegrationData InventoryUpdate ON Devices.DeviceID = InventoryUpdate.DeviceID
        JOIN CustInv_ObjType_6121 BCMModulesVersions ON Devices.DeviceID = BCMModulesVersions.DeviceID
WHERE   InventoryUpdate.IntegrationDate IS NOT NULL
        AND Devices.TopologyType IN ('_DB_DEVTYPE_CLIENT_','_DB_DEVTYPE_RELAY_')
        AND BCMModulesVersions.InstanceName NOT IN ('PatchManagement','RemoteControl')
        AND 2 > ( SELECT COUNT(DISTINCT BCMModulesVersions.InstanceName)
                         FROM   CustInv_ObjType_6121 BCMModulesVersions
                         WHERE  Devices.DeviceID = BCMModulesVersions.DeviceID
                                AND BCMModulesVersions.InstanceName IN ('PatchManagementPremium','RemoteControl'))
ORDER BY Devices.DeviceName ASC; 

感谢大家的帮助!