【问题标题】:SQL Get List of Substrings Then Use as Values for LIKESQL 获取子字符串列表,然后用作 LIKE 的值
【发布时间】:2016-03-22 14:54:41
【问题描述】:

我想使用子字符串列表作为LIKE 子句的值。

考虑下表:

菌株

id    name
-------------------------------------------------------
562   B6;129 (Bnip3 KO)
563   B6;129 (BNIP3 Wt) [pregnant]
564   B6;129 (BNIP3 Wt) [older than 21 days]
720   BALB/C T(x:11)38H (T38H)
721   BALB/C [older than 21 days]

链接 (l)

id    protocol_id     strain_id
-------------------------------------------------------
1     61846           563
2     13487           564
3     79465           721
4     41699           720

动物(一)

id    group_id        strain_id
-------------------------------------------------------
24    9666            563
25    9666            720

通常我会提供一个我尝试过的查询,但这次我什么都没有。相反,让我分解一下我需要做的步骤:

  1. 从同一group_id 下的所有动物的菌株名称中获取子字符串列表。
    • 为了得到子字符串,我想要()里面的字符串
    • 类似SELECT /* get the list of substrings */ FROM animals a LEFT JOIN strains s ON s.id = a.strain_id WHERE a.group_id = 9666
    • 在本例中,我需要以下列表:(BNIP3 Wt)(T38H)
    • 如果()中包含多个值,则使用最后一个
  2. 使用上述LIKE 子句的结果列表来获取protocol_id 的列表,其菌株名称包含子字符串。

我对解决方案的想法

SELECT l.protocol_id
FROM links l
LEFT JOIN strains s
ON s.id = l.strain_id
WHERE s.name LIKE (/* put the list here with the % for wildcards */)

我想要得到的最终结果如下:

protocol_id
------------------------------
61846
13487
41699

【问题讨论】:

标签: sql oracle substring


【解决方案1】:

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE Strains (id, name ) AS
SELECT 562,   'B6;129 (Bnip3 KO)' FROM DUAL UNION ALL
SELECT 563,   'B6;129 (BNIP3 Wt) [pregnant]' FROM DUAL UNION ALL
SELECT 564,   'B6;129 (BNIP3 Wt) [older than 21 days]' FROM DUAL UNION ALL
SELECT 720,   'BALB/C T(x:11)38H (T38H)' FROM DUAL UNION ALL
SELECT 721,   'BALB/C [older than 21 days]' FROM DUAL;

CREATE TABLE Links (id, protocol_id, strain_id ) AS
SELECT 1,     61846,           563 FROM DUAL UNION ALL
SELECT 2,     13487,           564 FROM DUAL UNION ALL
SELECT 3,     79465,           721 FROM DUAL UNION ALL
SELECT 4,     41699,           720 FROM DUAL;

CREATE TABLE Animals (id, group_id, strain_id ) AS
SELECT 24,    9666,            563 FROM DUAL UNION ALL
SELECT 25,    9666,            720 FROM DUAL;

查询 1

SELECT l.protocol_id
FROM   links l
       INNER JOIN strains s
       ON s.id = l.strain_id
       INNER JOIN (
         SELECT REGEXP_SUBSTR( s.name, '\(.*?\)', 1, l.COLUMN_VALUE ) AS id
         FROM   strains s,
                TABLE( 
                  CAST(
                    MULTISET(
                      SELECT LEVEL
                      FROM   DUAL
                      CONNECT BY LEVEL <= REGEXP_COUNT( s.name, '\(.*?\)' )
                    ) AS SYS.ODCINUMBERLIST
                  )
                ) l,
                animals a
         WHERE  a.strain_id = s.id
         AND    a.group_id = 9666
       ) t
       ON s.name LIKE '%' || t.id || '%'

Results

| PROTOCOL_ID |
|-------------|
|       61846 |
|       13487 |
|       41699 |
|       41699 |

【讨论】:

  • 这看起来不错,但是您是如何获得传递给 SYS.ODCIVARCHAR2LIST 的值的?
  • 菌株名称的子串不得硬编码。
  • @PatrickGregorio 已更新 - 如果您只需要唯一值,请添加 DISTINCT
  • 根据您的 SQL Fiddle,我可以确认这是可行的。您不使用SUBSTRINSTR 有什么原因吗?我认为这两个应该足够了(目前正在阅读如何使用它们)。
  • 我在我的实际数据上尝试了你的解决方案,即使使用DISTINCT,我也得到了很多protocol_id。您的解决方案是否会忽略找不到任何 () 的行?
【解决方案2】:

您也许可以使用 REGEXP_LIKE 解决问题

例如

With strains (id, name) as
(
          select 562,   'B6;129 (Bnip3 KO)' from dual
union all select 563,   'B6;129 (BNIP3 Wt) [pregnant]'  from dual
union all select 564,   'B6;129 (BNIP3 Wt) [older than 21 days]'  from dual
union all select 720,   'BALB/C T(x:11)38H (T38H)'  from dual
union all select 721,   'BALB/C [older than 21 days]'  from dual
)
    ,Links (id, protocol_id, strain_id ) as
(    
          select 1,     61846,           563 from dual
union all select 2,     13487,           564 from dual
union all select 3,     79465,           721 from dual
union all select 4,     41699,           720 from dual
)
   ,Animals (id, group_id, strain_id) as
(   
          select 24,    9666,            563 from dual
union all select 25,    9666,            720 from dual
)
SELECT l.protocol_id
FROM links l
LEFT JOIN strains s ON s.id = l.strain_id
WHERE  REGEXP_LIKE (s.name, '*BNIP3|T38H*');

【讨论】:

  • 请不要对菌株名称进行硬编码。那对我不起作用。我需要知道如何获得这些值。
  • 您可以使用 REGEXP_SUBSTR 获取值
猜你喜欢
  • 1970-01-01
  • 2010-10-17
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-05
  • 2012-01-12
  • 1970-01-01
相关资源
最近更新 更多