db2 将逗号分隔数据转换为多值IN列表
原文:http://book.csdn.net/bookfiles/530/10053017906.shtml
6.11 将分隔数据转换为多值IN列表
问题
已经有了分隔数据,想要将其转换为WHERE子句IN列表中的项目。考虑下面的字符串:
7654,7698,7782,7788
要将该字符串用在WHERE子句中,但是下面的SQL语句是错误的,因为EMPNO是一个数值列:
select ename,sal,deptno
from emp
where empno in ( '7654,7698,7782,7788' )
因为EMPNO是一个数值列,而此IN列表是一个字符串值,所以此SQL语句会失败。现要将此字符串转换为用逗号分解的数值列表。
解决方案
表面上看SQL应该将分隔字符串作为一个分隔值列表对待,但是实际情况不是这样。当SQL遇到括在引号中的逗号时,并不知道此符号表示多值列表,SQL必须将括在引号中的内容作为一个整体对待,也就是一个字符串值。因此必须将字符串分解为各个单独的EMPNO。这种解决方案的关键就是需要遍历字符串,但并不是一个字符一个字符地遍历,而是要将这个字符串转换为有效的EMPNO值。
DB2
通过遍历传递给IN列表的字符串,可以很轻松地将其转换为若干行。在这里函数ROW_NOMBER、LOCATE和SUBSTR尤其有用:
1 select empno,ename,sal,deptno
2 from emp
3 where empno in (
4 select cast(substr(c,2,locate(',',c,2)-2) as integer) empno
5 from (
6 select substr(csv.emps,cast(iter.pos as integer)) as c
7 from (select ','||'7654,7698,7782,7788'||',' emps
8 from t1) csv,
9 (select id as pos
10 from t100 ) iter
11 where iter.pos <= length(csv.emps)
12 ) x
13 where length(c) > 1
14 and substr(c,1,1) = ','
15 ) y
MySQL
通过遍历传递给IN列别的字符串,可以很轻松地将其转换为若干行:
1 select empno, ename, sal, deptno
2 from emp
3 where empno in
4 (
5 select substring_index(
6 substring_index(list.vals,',',iter.pos),',',-1) empno
6 from (select id pos from t10) as iter,
7 (select '7654,7698,7782,7788' as vals
8 from t1) list
9 where iter.pos <=
10 (length(list.vals)-length(replace(list.vals,',','')))+1
11 ) x
Oracle
通过遍历传递给IN列别的字符串,可以很轻松地将其转换为若干行。这里函数ROWNUM,SUBSTR和INSTR尤其有用:
1 select empno,ename,sal,deptno
2 from emp
3 where empno in (
4 select to_number(
5 rtrim(
6 substr(emps,
7 instr(emps,',',1,iter.pos)+1,
8 instr(emps,',',1,iter.pos+1) -
9 instr(emps,',',1,iter.pos)),',')) emps
10 from (select ','||'7654,7698,7782,7788'||',' emps from t1) csv,
11 (select rownum pos from emp) iter
12 where iter.pos <= ((length(csv.emps)-
13 length(replace(csv.emps,',')))/length(','))-1
14 )
Postgres
通过遍历传递给IN列别的字符串,可以很轻松地将其转换为若干行。使用函数 SPLIT_PART可以简化将字符串解析为单独的数值列表的工作:
1 select ename,sal,deptno
2 from emp
3 where empno in (
4 select cast(empno as integer) as empno
5 from (
6 select split_part(list.vals,',',iter.pos) as empno
7 from (select id as pos from t10) iter,
8 (select ','||'7654,7698,7782,7788'||',' as vals
9 from t1) list
10 where iter.pos <=
11 length(list.vals)-length(replace(list.vals,',',''))
12 ) z
13 where length(empno) > 0
14 ) x
SQL Server
通过遍历传递给IN列别的字符串,可以很轻松地将其转换为若干行。这里函数ROW_NUMBER、CHARINDEX和SUBSTRING尤其有用:
1 select empno,ename,sal,deptno
2 from emp
3 where empno in (select substring(c,2,charindex(',',c,2)-2) as empno
4 from (
5 select substring(csv.emps,iter.pos,len(csv.emps)) as c
6 from (select ','+'7654,7698,7782,7788'+',' as emps
7 from t1) csv,
8 (select id as pos
9 from t100) iter
10 where iter.pos <= len(csv.emps)
11 ) x
12 where len(c) > 1
13 and substring(c,1,1) = ','
14 ) y
讨论
这种解决方案中第一步,也是最重要的一步就是遍历字符串。一旦完成了这步操作,剩下的操作就是使用DBMS提供的函数来将字符串解析为单独的数值。
DB2和SQL Server
内联视图X(第6~11行)遍历字符串,这里用的是“穿越”字符串的思想,所以其每一行都比其上一行少一个字符:
,7654,7698,7782,7788,
7654,7698,7782,7788,
654,7698,7782,7788,
54,7698,7782,7788,
4,7698,7782,7788,
,7698,7782,7788,
7698,7782,7788,
698,7782,7788,
98,7782,7788,
8,7782,7788,
,7782,7788,
7782,7788,
782,7788,
82,7788,
2,7788,
,7788,
7788,
788,
88,
8,
,
注意,因为整个字符串是由逗号(分界符)括起来的,所以不需要特殊的检查来确定字符串从哪里开始及到哪里结束:
下一步是只保留要用于内部列表中的值。除了最后只有单独逗号的一行之外,保留以逗号开头的行。使用SUBSTR或SUBSTRING函数来识别哪些行以逗号开头,并保留在此行中到下一个逗号之间的所有字符。此操作完成后,将字符串转换为数值,这样就可以用来正确地跟数值列EMPNO运算了(行4~14):
EMPNO
------
7654
7698
7782
7788
最后,使用在子查询中的结果来返回想要得到的行。
MySQL
内联视图(行5~9)遍历字符串。第10行的表达式通过查找逗号(分隔符)的数量来确定在字符串中有多少个值并加1。函数SUBSTRING_INDEX(第6行)返回在字符串中第n个逗号(分隔符)之前(到它左边)的所有字符:
+---------------------+
| empno |
+---------------------+
| 7654 |
| 7654,7698 |
| 7654,7698,7782 |
| 7654,7698,7782,7788 |
+---------------------+
这些行随后传递给SUBSTRING_INDEX(第5行)函数的另一次调用,此时第n个分隔符参数为-1,这表示在第n个分隔符右边所有的值需要保留。
+-------+
| empno |
+-------+
| 7654 |
| 7698 |
| 7782 |
| 7788 |
+-------+
最后一步是将结果加入到一个子查询中。
Oracle
第一步是遍历字符串:
select emps,pos
from (select ','||'7654,7698,7782,7788'||',' emps
from t1) csv,
(select rownum pos from emp) iter
where iter.pos <=
((length(csv.emps)-length(replace(csv.emps,',')))/length(','))-1
EMPS POS
--------------------- ----------
,7654,7698,7782,7788, 1
,7654,7698,7782,7788, 2
,7654,7698,7782,7788, 3
,7654,7698,7782,7788, 4
有多少行返回,就表示在列表中有多少个值。POS值对于查询是至关重要的,因为要用它来将字符串分解为单独的值。使用SUBSTR和INSTR函数来分解字符串,POS用来确定在每个字符串中第n个分隔符的位置。由于字符串是用逗号括起来的,所以不需要特殊的检测手段来确定字符串的开始位置与结束位置。传递给SUBSTR,INSTR(7~9行)确定第n个和第n+1个分隔符的位置。用下一个逗号的位置值(字符串中下一个逗号的位置)减去当前逗号的位置值(字符串中当前逗号的位置),就可以从字符串中提取出每个值。
select substr(emps,
instr(emps,',',1,iter.pos)+1,
instr(emps,',',1,iter.pos+1) -
instr(emps,',',1,iter.pos)) emps
from (select ','||'7654,7698,7782,7788'||',' emps
from t1) csv,
(select rownum pos from emp) iter
where iter.pos <=
((length(csv.emps)-length(replace(csv.emps,',')))/length(','))-1
EMPS
-----------
7654,
7698,
7782,
7788,
最后一步就是删除每个值后面的逗号,将其转换为数值并且将其插入到子查询中。
PostgreSQL
内联视图Z(6~9行)遍历字符串,返回行的数量也就是在字符串中有多少值。要找出在字符串中有多少值,用带有分隔符的字符串长度减去不带分隔符的字符串长度即可(第9行),函数SPLIT_PART用来分解字符串,该函数查找第n个分隔符之前的值。
SELECT列表.vals,
split_part(list.vals,',',iter.pos) as empno,
iter.pos
from (select id as pos from t10) iter,
(select ','||'7654,7698,7782,7788'||',' as vals
from t1) list
where iter.pos <=
length(list.vals)-length(replace(list.vals,',',''))
vals | empno | pos
-----------------------+-------+-----
,7654,7698,7782,7788, | | 1
,7654,7698,7782,7788, | 7654 | 2
,7654,7698,7782,7788, | 7698 | 3
,7654,7698,7782,7788, | 7782 | 4
,7654,7698,7782,7788, | 7788 | 5
最后一步就是将返回值(EMPNO)转换为数值,并且插入到子查询中。
db2 将逗号分隔数据转换为多值IN列表的更多相关文章
- 6.11 将分割数据转换为多值IN列表
问题 已经有了分隔数据,想要将其转换为WHERE子句IN列表中的项目.考虑下面的字符串: 7654,7698,7782,7788 要将该字符串用在WHERE子句中,但是下面的SQL语句是错误的,因为E ...
- .net c#将数据库数据对象转换为实体值对象
using System; using System.Data; namespace Sunlib { public static class DataHelper { //将数据库数据对象转换为实体 ...
- c语言实现灰度图转换为二值图
将上篇得到的灰度图转换为二值图,读取像素数据,低于某一值置0,否则设置为255,为得到更好的效果不同图片应采用不同的值 /* 2015年6月2日11:16:22 灰度图转换为二值图 blog:http ...
- 使用python将mysql数据库的数据转换为json数据
由于产品运营部需要采用第三方个推平台,来推送消息.如果手动一个个键入字段和字段值,容易出错,且非常繁琐,需要将mysql的数据转换为json数据,直接复制即可. 本文将涉及到如何使用Python访问M ...
- 将逗号分隔的字符串转换为Python中的列表
给定一个字符串: 它是由逗号分隔的几个值的序列: mStr = '192.168.1.1,192.168.1.2,192.168.1.3' 如何将字符串转换为列表? mStr = ['192.168. ...
- 深度学习原理与框架-Tfrecord数据集的制作 1.tf.train.Examples(数据转换为二进制) 3.tf.image.encode_jpeg(解码图片加码成jpeg) 4.tf.train.Coordinator(构建多线程通道) 5.threading.Thread(建立单线程) 6.tf.python_io.TFR(TFR读入器)
1. 配套使用: tf.train.Examples将数据转换为二进制,提升IO效率和方便管理 对于int类型 : tf.train.Examples(features=tf.train.Featur ...
- 深度学习原理与框架-递归神经网络-时间序列预测(代码) 1.csv.reader(进行csv文件的读取) 2.X.tolist(将数据转换为列表类型)
1. csv.reader(csvfile) # 进行csv文件的读取操作 参数说明:csvfile表示已经有with oepn 打开的文件 2. X.tolist() 将数据转换为列表类型 参数说明 ...
- 将日期或数据转换为char数据类型 TO_CHAR(x[[,c2],C3])
TO_CHAR(x[[,c2],C3])[功能]将日期或数据转换为char数据类型[参数]x是一个date或number数据类型.c2为格式参数c3为NLS设置参数如果x为日期nlsparm=NLS_ ...
- pandas神坑:如果列有NAN,则默认给数据转换为float类型!给pandas列指定不同的数据类型。
今天碰到一个错误,一个字典取值报keyError, 一查看key, 字符串类型的数字后面多了小数点0, 变成了float的样子了. 发现了pandas一个坑:如果列有NAN,则默认给数据转换为floa ...
随机推荐
- 基于UML的面向对象分析与设计
前言 经常听到有朋友抱怨,说学了UML不知该怎么用,或者画了UML却觉得没什么作用.其实,就UML本身来说,它只是一种交流工具,它作为一种标准化交流符号,在OOA&D过程 ...
- Android中 单位 介绍
看到有很多网友不太理解dp.sp和px的区别:现在这里介绍一下dp和sp.dp也就是dip.这个和sp基本类似.如果设置表示长度.高度等属性时可以使用dp 或sp.但如果设置字体,需要使用sp.dp是 ...
- Linux命令格式
- Apache重启报警,不存在虚拟主机目录(httpd.conf打开了一些扩展)
Apache重启时报警: AH00112: Warning: DocumentRoot [/usr/local/apache/docs/dummy-host.example.com] does not ...
- unity, animator stateMachine立即触发状态转换
例如按下键jump按钮人物执行跳起动作,同时动画状态由idle转换为jump,同时打开Game窗口和Animator窗口对比观察,发现人物跳起时动画状态并没有同步发生转换,而是有一定延迟,导致人物动画 ...
- Object-C中的字符串对象1-不可变字符串
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { ...
- [转]使用jquery-webcam插件,实现人脸采集并转base64
项目需求:在ie或chrome浏览器下,调用电脑摄像头(确保使用的是笔记本电脑,或者摄像头功能正常使用的台式机),进行人脸图像采集预览,并将图片的base64码传入到后台进行后续操作.该demo适用于 ...
- PKI/CA
PKI( Public Key Infrastructure )指的是公钥基础设施. CA ( Certificate Authority )指的是认证中心. PKI从技术上解决了网络通信安全的种种障 ...
- 喵神 onevcat 的直播首秀
喵神 onevcat 的直播首秀 王巍在圈内人称喵神,我和他在网上很早就认识,平时多有交流.在我眼中,他是一个幽默风趣高手.虽然他的博客中主要内容是 iOS 开发,但是他实际上涉及的技术领域还包括 ...
- GDB和WinDbg中调用函数
GDB: 特别简单,直接写调用式子即可,如下图的p word.c_str(),其中word的类型是std::string WinDbg:目前都说是.call命令,说实话我宁愿不用...见: http: ...