2017-07-07 33 views
0

时显示的结果,而得到的结果的参数我有一个查询select查询使用,或者在(甲骨文)子句

select columnX from tableA 
    where (columnY like '%string1%' or columnY like '%string2%'); 

,但我也想知道得到了所匹配的参数(字符串1或字符串2)因为它的我得到了我的结果,所以我修改我的查询到

select columnX value,'string1' pattern from tableA 
    where columnY like '%string1%' 
    union 
    select columnX,'string2' from tableA 
    where columnY like '%string2%' 

这给了我,我的结果,但使查询巨大的(因为我有去匹配所以基本上数以百计的模式我写整个查询每个参数),我非常怀疑这是做这件事的最好方法,是否有一些ot她的方式来做到这一点,我不必为我想匹配的所有模式写一个新的查询? 这可以通过简单地修改查询或我将不得不使用Oracle SQL的任何先进的结构进行什么,我需要做什么?

+1

你重新写不等同于原来的。在原文中,如果'string1'或'string2'或**两个**都匹配,则在输出中会得到一行。在重写时,如果两个字符串都匹配,则会得到两行。这是期望的结果? – mathguy

+0

理想情况下,我想要的结果是有columnX,和所有得到与特定columnX匹配的模式。 例如这样的结果对我来说很理想: ColumnX,pattern “value1”,“string1,string2” “value2”,“foo” –

回答

3

不要忘记有数百种模式要匹配的要求。那么使用case语句的解决方案是不切实际的,恐怕你不得不编辑数百个这样的解决方案。将比较字符串放在一个表中。在这里我通过使用CTE(compare_strings表)来模拟。如果你需要添加一个值来比较,你只需将其添加到compare_strings表和查询没有改变。要模拟,将'efs'编辑为'blah',然后您将拾取第1行。

尽管如此,根据您的示例,比较字符串将匹配它出现在columnY中的任何位置,即使字符串嵌入在另一个单词中,而这个单词可能不是您想要匹配的单词。为了得到更精确,你可能需要切换到使用REGEXP_LIKE在那里你可以定制正则表达式来满足您的需求。

SQL> WITH tableA(columnX, columnY) AS (
    SELECT 1, 'blah blah blah' FROM DUAL UNION 
    SELECT 2, 'string2'   FROM DUAL UNION 
    SELECT 3, 'string'   FROM DUAL UNION 
    SELECT 4, 'string1'   FROM DUAL UNION 
    SELECT 5, 'string1 string2' FROM DUAL UNION 
    SELECT 6, NULL    FROM DUAL UNION 
    SELECT 7, 'string3'   FROM DUAL 
    ), 
    COMPARE_STRINGS(description) AS (
    SELECT 'string1' FROM DUAL UNION 
    SELECT 'efs'  FROM DUAL UNION 
    SELECT 'string2' FROM DUAL UNION 
    SELECT 'Mata Hairy' FROM DUAL UNION 
    SELECT 'string3' FROM DUAL 
    ) 
    SELECT columnX, cs.description "hit string" 
    FROM TABLEA A CROSS JOIN COMPARE_STRINGS CS 
    WHERE a.columnY LIKE '%' || cs.description || '%' 
    ORDER BY columnX; 

    COLUMNX hit string 
---------- ---------- 
     2 string2 
     4 string1 
     5 string1 
     5 string2 
     7 string3 

请注意,您会在第5行中获得2个匹配,因为columnY包含compare_strings表中的2个条目。你需要决定你想如何处理。看到上面的警告。

编辑17年7月10日把每行多重命中串在一行。

改变查询使用LISTAGG():

SELECT columnX, 
    LISTAGG(cs.description, '|') WITHIN GROUP (ORDER BY columnX) hit_string 
    FROM TABLEA A CROSS JOIN COMPARE_STRINGS CS 
    WHERE a.columnY LIKE '%' || cs.description || '%' 
    GROUP BY columnX; 

SQL>/

    COLUMNX HIT_STRING 
---------- -------------------- 
     2 string2 
     4 string1 
     5 string1|string2 
     7 string3 
+0

非常感谢,这正是我所寻找的解决方案。 有没有一种方法可以修改它,使单列中的列中的所有命中字符串都被一些分隔符分开? –

+0

更新后显示LISTAGG如何实现此目的。我将它保存在我的SQL技巧文件夹中。 –

0

你可以与逻辑返回一个新列:

CASE WHEN columnY like '%string1%' THEN 'string1' 
     WHEN columnY like '%string2%' THEN 'string2' 
    END 
0
SELECT columnX, 
CASE 
    WHEN columnY like '%string1%' THEN 'string1' 
    WHEN columnY like '%string2%' THEN 'string2' 
    ELSE NULL 
END AS pattern 
FROM tableA 
WHERE (columnY like '%string1%' or columnY like '%string2%'); 

编辑:您还可以使用ISNULL('string1','value you want')如果“字符串1”和“字符串2”的值可能为空

0
with tableA as(
    select 'asd' columnY from dual union all 
    select 'string2' columnY from dual union all 
    select 'string' columnY from dual union all 
    select 'string1' columnY from dual union all 
    select 'string1 string2' columnY from dual 
) 

select * from (
    select tableA.*, 
    case when columnY like '%string1%' then 1 else 0 end+ 
    case when columnY like '%string2%' then 2 else 0 end as res 
    from tableA 
) t 
where res > 0 

如果res列是1,意味着columnY仅包含“字符串1”,如果res是2,这意味着,仅包含“字符串2”,并且如果res为3,则columnY包含'string1'和'string2'