列中以冒号分隔的列表中的Where子句

时间:2014-09-07 21:37:43

标签: sql oracle sql-execution-plan

寻找Oracle SQL查询的一些帮助

我有2张桌子

首先是USERS

User Name | User Type
----------------------
JOHN | OFFICE
BOB  | REMOTE
PAUL | OFFICE
LISA | REMOTE

然后我有一个Reports表,其中包含一个报告列表以及一个以冒号分隔的访问列表

REPORT NAME | ACCESS_LIST
---------------------------
REPORT_1  |  OFFICE:REMOTE
REPORT_2  |  OFFICE
REPORT_3  |  REMOTE

如果我以OFFICE用户的身份登录,那么查询应该返回

REPORT NAME
--------------
REPORT_1
REPORT_2

我对使用逗号分隔字符串的子句的三元组提出了各种建议,但没有一个能够做我正在寻找的事情

1确实有效

SELECT * FROM 
   (select regexp_substr(ACCESS_LIST,'[^:]+', 1, level) as USERTYPE,ID 
    FROM DF_DOC_STORE
    connect by regexp_substr(ACCESS_LIST, '[^:]+', 1, level) is not null) 
WHERE USERTYPE = 'OFFICE'

但是当我添加where子句时,查询从花费不到一秒的时间到运行到超过1分钟; DF_DOC_STORE表中只有10行,所以我真的不明白我的查询有什么问题,但显然我做错了

没有where子句的查询的解释计划是

Plan 
  SELECT STATEMENT  ALL_ROWS Cost: 3  Bytes: 26  Cardinality: 2             
  3 VIEW A14730. Cost: 3  Bytes: 26  Cardinality: 2  
  2 CONNECT BY WITHOUT FILTERING 
  1 TABLE ACCESS FULL TABLE A14730.DF_DOC_STORE  Cost: 3  Bytes: 190  Cardinality: 2

当我添加where子句时,它跳转到此

Plan 
 SELECT STATEMENT  ALL_ROWS Cost: 3  Bytes: 4,030  Cardinality: 2 
 3 VIEW A14730. Cost: 3  Bytes: 4,030  Cardinality: 2               
 2 CONNECT BY WITHOUT FILTERING                 
 1 TABLE ACCESS FULL TABLE A14730.DF_DOC_STORE Cost: 3  Bytes: 190  Cardinality: 2

1 个答案:

答案 0 :(得分:3)

我建议您尝试使用like。这是一个想法:

select *
form df_doc_store
where ':' || access_list || ':' like '%:' || 'OFFICE'  || ':';

这假设您知道当前用户的类型为'OFFICE'

我应该补充说,逗号或冒号分隔列表是存储此类信息的一种非常糟糕的方式。关系数据库中的常规方法是使用联结表,尽管Oracle也支持嵌套表。