PL / SQL“ Where”条件“ WHERE”子句

时间:2019-03-22 14:43:45

标签: plsql oracle12c

我正在尝试对表进行查询,并且在构建WHERE子句时遇到了麻烦。表的“ SUBCLASS”列的值类似于“ UN”或“ U *”。

“ U *”表示匹配“ U”和任何其他字符(例如UB,UC,...)。

表格如下:

PDO::ATTR_PERSISTENT

给出一个字符串UC12341001000012或UN12341001000012,我将如何构造WHERE子句。

我尝试过:

ID    ISC    SUBCLASS
---   ----   ---------
1     ABC        UN
2     DEF        UN
3     DEF        U*

,但它返回所有行。 (我在这里使用“ UC”,但实际上这是一个传递给存储过程的参数。)

因此,给定UC12341001000012,我应该得到第三条记录,给定UN12341001000012,我应该得到前两条记录。

1 个答案:

答案 0 :(得分:1)

存在完全匹配项时,(略)棘手的位不包括通配符U*行。子查询和联合等方法多种多样。该示例使用一个内联视图来标记和计数精确匹配和通配符匹配,然后过滤该内联视图:

select id, isc, subclass, exact, wild
from (
  select id, isc, subclass,
    case when subclass = substr(:str, 1, 2) then 'Y' end as exact,
    case when subclass = substr(:str, 1, 1) || '*' then 'Y' end as wild,
    count(case when subclass = substr(:str, 1, 2) then subclass end) over () as exact_cnt
  from mytable
  where subclass like substr(:str, 1, 1) || '%' -- optional
)
where exact = 'Y' or (wild = 'Y' and exact_cnt = 0)

我使用了:str绑定变量代替了较短的文字,部分原因是因为我认为它更清楚,而且因为仅使用UC并不明显,为什么我使用了更多变量比您多substr()个电话;因为使用更长的完整值,无论如何您只想看前两个。

您可以对其进行一些更改以不重复case表达式(然后再从另一层inline view / CTE开始计数),或者更改内部过滤器以显式查找case表达式正在检查的相同内容(或忽略它-取决于数量,索引...)等,但希望能为您带来灵感。

通过CTE提供样本子类数据:

var str varchar2(20);

exec :str := 'UC12341001000012';

-- CTE for sample data
with mytable (id, isc, subclass) as (
  select 1, 'ABC', 'UN' from dual
  union all select 2, 'DEF', 'UN' from dual
  union all select 3, 'DEF', 'U*' from dual
)
-- actual query
select id, isc, subclass
from (
  select id, isc, subclass,
    case when subclass = substr(:str, 1, 2) then 'Y' end as exact,
    case when subclass = substr(:str, 1, 1) || '*' then 'Y' end as wild,
    count(case when subclass = substr(:str, 1, 2) then subclass end) over () as exact_cnt
  from mytable
  where subclass like substr(:str, 1, 1) || '%' -- optional
)
where exact = 'Y' or (wild = 'Y' and exact_cnt = 0);

        ID ISC SU
---------- --- --
         3 DEF U*

exec :str := 'UN12341001000012';

<same query>

        ID ISC SU
---------- --- --
         1 ABC UN
         2 DEF UN
  

如果返回多行

如果您只想要完全匹配的行之一,则可以在内联视图中添加一个row_number()调用-并带有一个合适的order by用于您想要拆分领带的方式-然后添加到外部过滤器:

select id, isc, subclass
from (
  select id, isc, subclass,
    case when subclass = substr(:str, 1, 2) then 'Y' end as exact,
    case when subclass = substr(:str, 1, 1) || '*' then 'Y' end as wild,
    count(case when subclass = substr(:str, 1, 2) then subclass end) over () as exact_cnt,
    row_number() over (partition by subclass order by isc) as rn
  from mytable
  where subclass like substr(:str, 1, 1) || '%' -- optional
)
where (exact = 'Y' or (wild = 'Y' and exact_cnt = 0))
and rn =1

...,或者您可以最初选择所有三行,但对它们进行排序,以便在应用rownum过滤器之前将通配符排在最后:

select id, isc, subclass
from (
  select id, isc, subclass
  from mytable
  where subclass = substr(:str, 1, 2)
  or subclass = substr(:str, 1, 1) || '*'
  order by case when subclass like '_*' then 2 else 1 end,
    isc -- or however you want to split ties
)
where rownum = 1