首页 > 解决方案 > SQL“IN”子句使用同时包含/排除项目?

问题描述

我想就解决特定修订的最佳方式获得一些帮助。我有以下 SQL 查询:

SELECT * FROM PRODDTA.F4105
WHERE (COITM, COMCU) IN ((`"Set of Data 1"`))
    AND (COLOCN, COLEDG) NOT IN ((`"Set of Data 2"`));

我想要做的是修改是否有办法将这些项目合并为一个:

SELECT * FROM PRODDTA.F4105
WHERE (COITM, COMCU, COLOCN, COLEDG) IN ((`"Set of Data 1 & 2"`));

你知道这是否可以实现吗?

非常感谢提前,

标签: sqlplsql

解决方案


这实际上取决于他们来自哪里Set of data 1Set of data2来自哪里以及他们之间的关系是什么,我不得不想象一个真实世界的场景,这将是一个好主意。

ASet of Data这里实际上只是一组Recordswith Fields。它们Fields本质上是相互关联的,这就是为什么它们出现在一个单一的Record.


问题 1:这两组包含彼此不相关的数据:

Set of Data1可能完全不同Set of Data2,因此无法说它们可以组合。

想象两组:

设置1:

+-------+--------+
| color | animal |
+-------+--------+
| brown | dog    |
| white | dog    |
| black | dog    |
| green | parrot |
| green | turtle |
| brown | turtle |
+-------+--------+

设置2:

+------------+--------+
|    food    | flavor |
+------------+--------+
| pepper     | spicy  |
| water      |        |
| grapefruit | bitter |
| lemon      | sour   |
| candy      | sweet  |
+------------+--------+

一个查询 WHERE 子句:

WHERE (f1, f2) IN (SELECT color, animal FROM set1)
    AND (f3, f4) IN (SELECT food, flavor FROM set2)

在我们测试的地方没有写这个的好方法,因为和(f1, f2, f3, f4)之间没有关系。color | animalfood | flavor

如果我们在 crazytown,我们可以交叉连接这两个集合,以获得它们的笛卡尔积,产生与原始查询相同的结果集:

WHERE (f1, f2, f3, f4) IN (SELECT color, animal, food, flavor FROM set1, set2)

但是现在我们有一个子查询,其中包含set1xset2条记录的中间结果集。这很愚蠢,原因有很多:

  1. 两个集合上的索引被忽略
  2. 如果set1set2多于几条记录,您最终会得到一个巨大的中间结果集。
  3. 这两个集合之间没有任何关系,所以将它们组合在一起只是为了让你的 SQL 字符更少。
  4. 将有大量不必要的系统资源(CPU、磁盘、I/O)用于构建和存储此中间结果集,从而导致繁琐的缓慢查询。
  5. 任何其他开发人员一看到它就会追捕你并杀死你。如果他们打电话给我,我会提供逃跑的车。

问题 2:这两个集合可能彼此有关系,但是将IN条件更改为 1 会导致记录下降。

即使可以组合这两个集合,您最终可能仍会得到与原始查询不同的结果。想象:

设置1:

+-------+--------+
| color | animal |
+-------+--------+
| brown | dog    |
| white | dog    |
| black | dog    |
| green | parrot |
| green | turtle |
| brown | turtle |
+-------+--------+

第 2 组:

+--------+-------------+
| animal | stink_scale |
+--------+-------------+
| turtle |           2 |
| parrot |           4 |
| dog    |           5 |
| skunk  |          10 |
+--------+-------------+

表格1:

+-------+--------+---------+-------------+
| color | animal | animal2 | stink_scale |
+-------+--------+---------+-------------+
| white | dog    | dog     |           5 |
| brown | dog    | parrot  |           4 |
| green | turtle | turtle  |           2 |
+-------+--------+---------+-------------+

您要更改的查询:

SELECT * FROM table1 
WHERE (color, animal) IN (SELECT color, animal FROM Set1) 
    AND (animal2, stink_scale) IN (SELECT animal, stink_scale FROM set2);

这将产生 3 条记录 as white | dogis inset1dog | 5is in setas it brown | doginset1parrot | 4is inset2并且对于 in 中的第三条记录相同table1

但是,如果我们将这两组组合在它们的animal键上:

 SELECT set1.color, set1.animal, set2.animal as animal2, set2.stink_scale FROM set1 JOIN set2 ON set1.animal = set2.animal;

我们将得到集合:

+-------+--------+---------+-------------+
| color | animal | animal2 | stink_scale |
+-------+--------+---------+-------------+
| brown | dog    | dog     |           5 |
| white | dog    | dog     |           5 |
| black | dog    | dog     |           5 |
| green | parrot | parrot  |           4 |
| green | turtle | turtle  |           2 |
| brown | turtle | turtle  |           2 |
+-------+--------+---------+-------------+

我们用它来组合我们的IN条件:

 SELECT * 
 FROM table1
 WHERE (color, animal, animal2, stink_scale) IN (SELECT set1.color, set1.animal, set2.animal as animal2, set2.stink_scale FROM set1 JOIN set2 ON set1.animal = set2.animal)

我们只得到 2 条记录,因为在该子查询中没有结果brown | dog | parrot | 4将存在。


所以,最终除非有理由改变条件,从而改变结果集的定义,你最好不要管它。它确实改变了逻辑。


推荐阅读