首页 > 解决方案 > 具有依赖于多行的多个排列的查询

问题描述

(SQL2014 如果有影响的话)

说我有 [tableA]

id  ResultID  SampleID  ERRORCODE col4 colN

1   9001      1100      0         ...  ...
2   9002      1100      100       ...  ...
3   9003      1100      200       ...  ...
4   9004      1100      300       ...  ...
5   9005      1101      0         ...  ... 
6   9006      1101      0         ...  ...
7   9007      1101      0         ...  ...
8   9008      1101      0         ...  ...
9   9009      1102      0         ...  ...
10  9010      1102      100       ...  ...
11  9011      1102      200       ...  ...
12  9012      1102      0         ...  ...

我想生成一个只显示SampleID包含所有错误代码 0、100、200 和 300 的样本集(由公共 val 标识)的结果。即上述内容将减少为:

id  ResultID  SampleID  ERRORCODE col4 colN

1   9001      1100      0         ...  ...
2   9002      1100      100       ...  ...
3   9003      1100      200       ...  ...
4   9004      1100      300       ...  ...

因此,我需要一个查询,它一次查看多行并向下选择具有(i)列中某些键值的组,这里是[ERRORCODE],(ii)另一列中的值一致,这里是[SampleID]。我看过:

在多行上使用多个 IN 子句进行查询

却一点喜悦都没有。适用于 oliboon 的子查询对我来说只适用于一行。Olga 的代码根本不起作用,而 Aushin 的代码产生了意想不到的结果(删除一半的语法并没有改变它们)!

N00b 到 SQL,所以我有点失落!

列出的一些解决方案中使用的“table”关键字似乎对我不起作用 - 可能这些答案旨在创建一个子表,然后在子查询中对其解决方案进行进一步解析。如果我尝试以下操作,我得到的只是“关键字表附近的语法不正确”错误:

select distinct SampleID from table [my].[db].[path].[tableA]

我想到了格式的查询

SELECT *
From [tableA]
where
    [SampleID] in (Select [SampleID] from [tableA] where [ERRORCODE] = 0) and
    [SampleID] in (Select [SampleID] from [tableA] where [ERRORCODE] = 100) 

本来可以,但是如果两个 [ERRORCODE] 检查是针对相同的代码,即 100,它只会返回一个结果。这当然是无用的。它逐行检查,而不是执行逻辑门的第一部分,然后是第二部分。

如果我能够完成 [ERRORCODE]=0 的第一部分,然后从 [ERRORCODE]=100 的那些 SampleID 中向下选择并重复,那么就可以了。不知道该怎么做。

编辑:Ach FFS。事实证明,我正在寻找的每一个错误代码都必须相互排斥——无论是什么组合,都不能同时出现两个错误代码。我假设在我拥有的数据库的大小中,某处会有一个组合。

我用错误代码检查了我的查询,我可以从一个不合格的 SELECT * 中看到它们并排放置并证明它有效。

我想问题是无效的。

标签: sqlsql-serverssms-18

解决方案


我有点失落。如果您想要包含所有四个错误代码的样本,那么这应该可以满足您的需求:

select a.*
from [tableA] a
where a.SampleID in (Select a2.SampleID from tableA a2 where a2.ERRORCODE = 0) and
      a.SampleID in (Select a2.SampleID from tableA a2 where a2.ERRORCODE = 100) and
      a.SampleID in (Select a2.SampleID from tableA a2 where a2.ERRORCODE = 200) and
      a.SampleID in (Select a2.SampleID from tableA a2 where a2.ERRORCODE = 300) ;

这应该有效,尽管问题声称它没有。它不一定会有最好的性能。

我通常建议聚合以设置样本 ID:

select sampleid
from tablea
where errorcode in (0, 100, 200, 300)
group by sampleid
having count(distinct errorcode) = 4;

如果您不想重复并覆盖所有错误代码,请使用:

having count(distinct errorcode) = 4 and count(*) = 4

这也可能不是在所有情况下都具有最佳性能。但是性能是可以预测的——它几乎不会根据您要查找的代码数量而变化。该having子句可以使这变得非常通用。

然后,如果您想要所有原始数据,您可以使用joininexists

select a.*
from tablea a join
     (select sampleid
      from tablea
      where errorcode in (0, 100, 200, 300)
      group by sampleid
      having count(distinct errorcode) = 4
     ) a2
     on a2.sampleid = a.sampleid;
  

推荐阅读