如何构建包含多个步骤的大型查询?

时间:2021-06-10 19:31:31

标签: mysql

我有一些这样的数据(download 10,000 rows of sample data here)

id   parent sequence   mz1_monoisotopic 
---------------------------------------
1    0      SGVNHR     669.34           
2    0      IEEIATDLK  1030.99
3    0      AMDAWGAS   1030.07          
5    1      MDLILDDR   990.49
7    1      AAAGGGAG   1029.50           
8    1      LEVSEELIEK 1188.64     

我需要对其执行一系列步骤,但我不确定如何构建我的查询。以下是步骤:

  1. 展开这个表格。查看 sequence,并计算每个序列中 M 的数量。对于序列中的每个 M,创建一个新条目,其中 mz1_monoisotopic 的值增加 16。我使用递归公用表表达式实现了这一点(在底部查看代码

    id   parent sequence   mz1_monoisotopic  <--- THIS IS THE EXPANDED TABLE
    ---------------------------------------
    1    0      SGVNHR     1006.34           
    2    0      IEEIATDLK  1030.99
    3    0      AMDAWGAS   1030.07
    4    0      AMDAWGAS   1046.07   <--- NEW ROW! mz1_monoisotopic increased by 16.       
    5    1      MDLILDDR   990.49
    6    1      MDLILDDR   1006.49   <--- NEW ROW, mz1_monoisotopic increased by 16.
    7    1      AAAGGGAG   1029.50           
    8    1      LEVSEELIEK 1188.64 
    
  2. 使用用户定义的值列表(长度可变)——比如说 [1006, 1030, 1351 ...],搜索这个新的扩展表(从步骤 1 开始)并找到 {{1 }} 在每个值 (mz1_monoisotopic) 的 1 个单位内。每个值可以匹配多个 WHERE mz1_monoisotopic BETWEEN value - 1 AND value + 1,但只能返回一个匹配 PER parents。因此,值 parent 在第 2、3 和 7 行的 1 个单位内。其中两个来自 1030,因此它必须选择误差最低的一个。其中之一来自 parent == 0 1,因此它可以保留它。一些预期的输出:

    parent
  3. 将每个单独查询的结果合并到一个表中

    #RESULT FROM QUERYING WITH 1006:
    
    id   parent sequence   mz1_monoisotopic 
    ---------------------------------------
    1    0      SGVNHR     1006.34 
    6    1      MDLILDDR   1006.49    
    
    #RESULT FROM QUERYING WITH 1030:
    
    id   parent sequence   mz1_monoisotopic 
    ---------------------------------------
    3    0      AMDAWGAS   1030.07
    7    1      AAAGGGAG   1029.50    
    
    ...
    

我不知道从哪里开始,如果我想像数组一样单独查询数字列表,正如我所提到的。我需要帮助将这些转换为更大的单一查询。这是我第 1 步的 CTE:

 id   parent sequence   mz1_monoisotopic 
 ---------------------------------------
 1    0      SGVNHR     1006.34           
 3    0      AMDAWGAS   1030.07     
 6    1      MDLILDDR   1006.49   
 7    1      AAAGGGAG   1029.50           

这是选择错误最少的行的查询,按WITH RECURSIVE cte (id, parent, sequence, mz1_monoisotopic, missed_cleavages, MSO) AS ( SELECT id, parent, sequence, (mz1_monoisotopic + ((CHAR_LENGTH(sequence) - CHAR_LENGTH(REPLACE( sequence, 'C', ''))) * 57) # More fixed mods ) as mz1_monoisotopic, missed_cleavages, 0 AS MSO FROM `1_plant_trypsin_dig` UNION ALL SELECT id, parent, sequence, `mz1_monoisotopic` + 15.999 AS `mz1_monoisotopic`, missed_cleavages, MSO + 1 FROM cte WHERE MSO < (CHAR_LENGTH(sequence) - CHAR_LENGTH(REPLACE( sequence, 'M', ''))) ) 分组:

parent

1 个答案:

答案 0 :(得分:1)

好的,所以我不会详细介绍与扩展表格有关的任何细节,因为您似乎自己正确地管理了这一点。

第二个问题可以用一个搜索表和一个分区的 ROW_NUMBER() 来解决。

当我们假设以下基表设置时:

CREATE TABLE 1_plant_trypsin_dig (
  id INT,
  parent INT,
  sequence VARCHAR(50),
  mz1_monoisotopic DECIMAL(10,2)
);
INSERT INTO 1_plant_trypsin_dig VALUES (1, 0, 'SGVNHR', 1006.34);
INSERT INTO 1_plant_trypsin_dig VALUES (2, 0, 'IEEIATDLK', 1030.99);
INSERT INTO 1_plant_trypsin_dig VALUES (3, 0, 'AMDAWGAS', 1030.07);
INSERT INTO 1_plant_trypsin_dig VALUES (4, 0, 'AMDAWGAS', 1046.07);
INSERT INTO 1_plant_trypsin_dig VALUES (5, 1, 'MDLILDDR', 990.49);
INSERT INTO 1_plant_trypsin_dig VALUES (6, 1, 'MDLILDDR', 1006.49);
INSERT INTO 1_plant_trypsin_dig VALUES (7, 1, 'AAAGGGAG', 1029.50);
INSERT INTO 1_plant_trypsin_dig VALUES (8, 1, 'LEVSEELIEK', 1188.64);

和这样的搜索表(这可能是一个特定于连接的临时表,以支持多用户场景):

CREATE TABLE search (
  mz1_monoisotopic DECIMAL(10,2)
);
INSERT INTO search VALUES (1006.00);
INSERT INTO search VALUES (1030.00);

那么 - 假设我们将“错误”定义为实际 mz1_monoisotopic 和搜索到的 mz1_monoisotopic 之间的绝对差异 - 我们可以这样做:

SELECT id, parent, sequence, mz1_monoisotopic, err FROM (
  SELECT 
    d.id,
    d.parent,
    d.sequence,
    d.mz1_monoisotopic,
    ABS(d.mz1_monoisotopic - s.mz1_monoisotopic) err,
    ROW_NUMBER() over (
      PARTITION BY s.mz1_monoisotopic, d.parent
      ORDER BY ABS(d.mz1_monoisotopic - s.mz1_monoisotopic), id
    ) rn
  FROM
    1_plant_trypsin_dig d
    INNER JOIN search s ON
      d.mz1_monoisotopic BETWEEN s.mz1_monoisotopic - 1 AND s.mz1_monoisotopic + 1
) result WHERE rn = 1;

并收到此结果:

id    parent   sequence    mz1_monoisotopic   err
1     0        SGVNHR      1006.34            0.34
6     1        MDLILDDR    1006.49            0.49
3     0        AMDAWGAS    1030.07            0.07
7     1        AAAGGGAG    1029.50            0.50

请记住,您需要为 ROW_NUMBER() 订单定义决胜局,以防两行具有相同的错误值。我用过 id,您的偏好可能会有所不同。

请参阅 https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=75738999738d10b03e43fb768267eefc

的现场示例
相关问题