想象表t1有2个cols:
col1 col2
--------------
test 900 1
test 901 2
test 902 3
user 901 4
test 909 5
我想找到一行2个参数(名称,代码),其中名称为(test,user ..etc)和代码 - (901,902,null,.. etc)。 不能有多行相同(代码,名称) - 我的意思是在Col1中没有2行有“test 901”。
代码:
declare
name varchar2(30);
code varchar(10);
col_val varchar2(30);
col2_val numeric;
begin
name:= 'test';
code := '900';
select col1, col2 into col_val, col2_val
from t1
where
( REGEXP_LIKE(col1, name||'\s+'||code) -- (3)
or (
not REGEXP_LIKE(col1, name||'\s+'||code) -- (1)
and REGEXP_LIKE(col1, name) -- (2)
)
)
order by col1;
DBMS_OUTPUT.PUT_LINE('val:'||col_val||' id:'||col2_val);
end;
1)测试值名称:='test'代码:='900'结果应为“val:test 900 id:1” - 没关系。
2)但名称:='test'代码:= '909'结果应为“val:test 909 id:5 ”,但我得到了“val:test 900 id:1”(Name ='Test'的第一行) - 这不是我想要的。
3)以防名称:='test'代码:= '999'结果应为“val:test 900 id:1”(没有999代码,所以我需要只是里面有Name ='test'的任何行。
主要问题是为什么oracle忽略(1)子句为2)例子? 也许我做错了 - 所以如果你能表明我的错误就会很棒!
答案 0 :(得分:0)
你不能像这样组合ROWNUM和ORDER BY,因为ROWNUM是之前的行号。
你需要更详细并写一些像
这样的东西 select a.* from (
select * from table order by col1 ) a
where rownum = 1;
查看ROWNUM和分页的文档。
答案 1 :(得分:0)
这个条件:
(REGEXP_LIKE(col1, :name || '\s+' || :code)
OR (NOT REGEXP_LIKE(col1, :name || '\s+' || :code) AND REGEXP_LIKE(col1, :name))
将匹配示例中的所有行。
搜索test 909
时,您正在匹配'test 909' OR (NOT 'test 909' AND 'test')
。这将匹配从'test'
开始的每一行(每个第一个条件或每秒)。
由于您使用的是rownum = 1
,因此返回的第一列匹配为'test 900'
如果你想要一个后备匹配(如果它存在则返回'test 909'
,否则返回任何'test'
),请使用:
SELECT *
FROM (
SELECT *
FROM t1
WHERE REGEXP_LIKE(col1, name || '\s+' || code)
UNION ALL
SELECT *
FROM t1
WHERE REGEXP_LIKE(col1, name)
)
WHERE rownum = 1
,或者,如果您不喜欢UNION
s:
SELECT *
FROM (
SELECT *
FROM t1
WHERE REGEXP_LIKE(col1, name)
ORDER BY
CASE WHEN REGEXP_LIKE(col1, name || '\s+' || code) THEN 0 ELSE 1 END
)
WHERE rownum = 1
但后者的效率较低,因为它必须排序。
答案 2 :(得分:0)
将col1的各个部分存储在不同的列中会更好。无论如何,除了Thilo所说的,还有一件事。
忽略rownum部分,表的四行与示例中的WHERE子句匹配。英语中的WHERE子句是“名称和代码都匹配,否则它们不匹配,但名称匹配。”
这是一种说“名称匹配”的复杂方式,如果这就是你的意思,就不需要这么复杂的WHERE子句。
(如果\ s表示空格,我不确定,它是“名称匹配,名称后面有空格。”)如果您希望在仅限名称匹配之前看到“两个”匹配,选择此“评分”顺序中的第一行:
ORDER BY
CASE WHEN REGEXP_LIKE(col1, name||'\s+'||code) THEN 2
WHEN REGEXP_LIKE(col1, name||'\s+) THEN 1
ELSE 0 END DESC
对评论的回应:
您的WHERE子句无法表达您的要求的但如果不是...... 方面。你的WHERE子句只表达如果有CODE和NAME的行或者只有NAME的行,请显示,这不是你的要求。
要表达 WHERE A,但如果不是A,那么B ,它将不起作用
WHERE <condition A> OR <condition B>
你必须写
WHERE <condition A> OR (NOT <condition A> AND <condition B>)
或做我喜欢的CASE表达式。
这有帮助吗?