Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String Oracle SQL中的减法字符串列表_String_Oracle_Oracle12c - Fatal编程技术网

String Oracle SQL中的减法字符串列表

String Oracle SQL中的减法字符串列表,string,oracle,oracle12c,String,Oracle,Oracle12c,我有两个表,用户在他们的服务中。由于user\u services表的大小,转换为行实际上并不实际(大多数用户有100个服务)。我怎样才能从一个列表中减去另一个列表 user_services (aprox 2mi recrods) USER SERVICES Rick 1,3,2,66,19 Jerry 1,2,19 serices_remove serv_rm 1,16,19,32 output USER SERVICES Rick 3,2,66 Je

我有两个表,用户在他们的服务中。由于
user\u services
表的大小,转换为行实际上并不实际(大多数用户有100个服务)。我怎样才能从一个列表中减去另一个列表

user_services (aprox 2mi recrods)
USER    SERVICES    
Rick    1,3,2,66,19
Jerry   1,2,19

serices_remove
serv_rm
1,16,19,32

output
USER    SERVICES
Rick    3,2,66
Jerry   2

我正在使用Oracle 12c。

我仍然建议将逗号分隔的值转换为行。在查询的两端操作这些CSV列既繁琐又容易出错,而且不会很好地执行。使用这种设置,您将无法使用索引

另一方面,考虑:

  • 一种查找表,其中每条记录存储一个用户id和一个(单个)关联的服务
  • 一种排除表,其中每条记录表示要删除的服务
在大型数据集上,索引扫描比完全扫描快一个数量级:使用相关索引,只需25次比较就可以定位1000万行中的相关记录(10 M的log2为23.5)

这还允许您将查询简化为:

SELECT l.*
FROM lookup_table l
LEFT JOIN exclusion_table e ON e.service = l.service
WHERE e.service IS NULL
或:

如果需要按用户聚合,则可以使用SQL函数(或者更好的是在表示层)来处理

提示:这是一个可以用来初始化新表的查询;它将CSV列拆分为新行:

select distinct usr, trim(regexp_substr(serv, '[^,]+', 1, level)) serv
from (SELECT usr, services serv FROM user_services) t
connect by instr(serv, ',', 1, level - 1) > 0
请参见

 with user_services as (
     select 'Rick' usr, '1,3,2,66,19' services from dual
     union select 'Jerry', '1,2,19' from dual
 )
 select distinct usr, trim(regexp_substr(serv, '[^,]+', 1, level)) serv
 from (SELECT usr, services serv FROM user_services) t
 connect by instr(serv, ',', 1, level - 1) > 0
      order by 1,2
USR | SERV :---- | :--- 杰瑞| 1
杰里| 19
杰里| 2
瑞克| 1
里克| 19
里克| 2
里克| 3
里克| 66

我仍然建议将逗号分隔的值转换为行。在查询的两端操作这些CSV列既繁琐又容易出错,而且不会很好地执行。使用这种设置,您将无法使用索引

另一方面,考虑:

  • 一种查找表,其中每条记录存储一个用户id和一个(单个)关联的服务
  • 一种排除表,其中每条记录表示要删除的服务
在大型数据集上,索引扫描比完全扫描快一个数量级:使用相关索引,只需25次比较就可以定位1000万行中的相关记录(10 M的log2为23.5)

这还允许您将查询简化为:

SELECT l.*
FROM lookup_table l
LEFT JOIN exclusion_table e ON e.service = l.service
WHERE e.service IS NULL
或:

如果需要按用户聚合,则可以使用SQL函数(或者更好的是在表示层)来处理

提示:这是一个可以用来初始化新表的查询;它将CSV列拆分为新行:

select distinct usr, trim(regexp_substr(serv, '[^,]+', 1, level)) serv
from (SELECT usr, services serv FROM user_services) t
connect by instr(serv, ',', 1, level - 1) > 0
请参见

 with user_services as (
     select 'Rick' usr, '1,3,2,66,19' services from dual
     union select 'Jerry', '1,2,19' from dual
 )
 select distinct usr, trim(regexp_substr(serv, '[^,]+', 1, level)) serv
 from (SELECT usr, services serv FROM user_services) t
 connect by instr(serv, ',', 1, level - 1) > 0
      order by 1,2
USR | SERV :---- | :--- 杰瑞| 1
杰里| 19
杰里| 2
瑞克| 1
里克| 19
里克| 2
里克| 3
里克| 66

好的关系方法是,使用一个具有单个键的子服务表和一个包含要删除的服务键的删除表。你可以通过拆分你的csv列表来转换到这个场景,这个网站上有很多例子。谢谢。将重新考虑拆分为行。关系方法是使用一个具有单个键的子服务表和一个包含要删除的服务键的删除表。你可以通过拆分你的csv列表来转换到这个场景,这个网站上有很多例子。谢谢。将重新考虑拆分为行。