在sql

时间:2018-05-20 17:48:22

标签: mysql sql notin

如何编写以下查询而不使用Not IN。由于IN的性能原因,不是不可取的。

select d.cert_serial_number as str from mdm_device d where d.client_id in (:CLIENT_IDS) and d.cert_serial_number not in (Select cert_serial_number from mdm_device where client_id not in (:CLIENT_IDS))

感兴趣的表列:

| cert_serial_number | client_id  |
+--------------------+------------+
|                102 | 1073741835 | 
|                102 | 1073741836 | 
|                102 | 1073741837 |
|                102 | 1073741838 | 
|                102 | 1073741839 | 
|                103 | 1073741840 | 
|                103 | 1073741831 | 
+--------------------+------------+------------+

如果cliend ids输入为1073741835,1073741836,则输出应为空 如果cliend id输入为1073741835,1073741836,1073741837,1073741838,1073741839,则输出应为102.

编辑: 我最终使用以下查询: SELECT d.cert_serial_number AS str FROM mdm_device d其中d.client_id in(:CLIENT_IDS)AND NOT EXISTS(SELECT 1 FROM mdm_device e WHERE d.cert_serial_number = e.cert_serial_number AND d.client_id!= e.client_id)

2 个答案:

答案 0 :(得分:0)

假设您的查询正确无误,您可以使用not exists

select d.cert_serial_number as str
from mdm_device d
where d.client_id in (:CLIENT_IDS) and
      not exists (select 1
                  from mdm_device d2
                  where d2.cert_serial_number = d.cert_serial_number and
                        d2.client_id not in (:CLIENT_IDS)
                 );

或者您可以使用聚合:

select d.cert_serial_number as str
from mdm_device d
group by d.cert_serial_number
having sum(d2.client_id in (:CLIENT_IDS)) = count(*);

也就是说,只返回具有这些序列号且没有其他序列号的设备。

答案 1 :(得分:0)

您的问题在性能方面是明智的:如果您缺少有价值的索引或重要的列来捕获系统的基本要求,那么没有查询可以解决您的性能问题。

哪些客户端不希望cert_serial_number包含在您的结果中?您是否可能错过了一个非常有助于将这些客户证书与结果区别开来的专栏?

我的解决方案:我建议您回到自己的要求并重新评估。我非常确定其中一个会在某个地方生成一个列,并且会帮助您获得您期望的性能结果。