【问题标题】:Query with multiple permutations that depend on multiple rows具有依赖于多行的多个排列的查询
【发布时间】:2021-05-07 09:50:19
【问题描述】:

(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         ...  ...

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

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]。我看过:

Query with multiple IN clause on multiple rows

但没有任何快乐。适用于 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 * 中看到它们并排放置并证明它有效。

我想问题是无效的。

【问题讨论】:

  • 用你的 DBMS 标记问题,我猜是 sql-server。
  • 我不明白为什么您显示的查询不起作用。添加两个缺少的 IN 子句,您应该得到所有样本 ID 为 1100 的行。当然,您应该添加一个 ORDER BY 子句,以按您想要的顺序获取行。
  • "我想这个问题是无效的。" - 好的,然后删除它:-)

标签: sql sql-server ssms-18


【解决方案1】:

您可以使用top(1) with ties .. order by 跳过除第一个SampleID + ERRORCODE 组合之外的所有组合。然后统计与code匹配的行数,一定是code的个数。

with codes as (
    select 0 c union all
    select 100 union all
    select 200 union all
    select 300
),
errlog as ( 
   -- take only first occurence of SampleID + ERRORCODE
   select top(1) with ties id,  ResultID,  SampleID,  ERRORCODE, col4, colN
   from [my].[db].[path].[tableA]
   order by row_number() over(partition by SampleID, ERRORCODE order by ResultID)
)
select id,  ResultID,  SampleID,  ERRORCODE, col4, colN
from (
   select t.*, count(*) over(partition by t.SampleID) cnt
   from errlog t
   join codes on codes.c = t.ERRORCODE
) t
where cnt = (select count(*) from codes);

【讨论】:

  • 我知道你在做什么 - 但在“where”附近出现不正确的语法错误(悬停会产生消息“期望 AS、ID 或 QUOTED_ID”)
  • 检查语法dbfiddle.uk/…,没问题
  • 嗯,不知道 - 即使修改了我知道存在一组的代码,这里的 SSMS 上的语法错误相同。
  • 感谢 Serg 的帮助 - 查看最新编辑 - 原来它们都是互斥的。
【解决方案2】:

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

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 子句可以让它变得非常通用。

那么,如果你想要所有的原始数据,你可以使用joinin,或者exists

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;
  

【讨论】:

  • 嗨 Gordon,感谢您的回复 - 作为最新更新 - 它们必须都是互斥的,因为查询确实适用于已知组合。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 1970-01-01
相关资源
最近更新 更多