数据库拆分的复杂问题!!

yujohny 2006-10-24 07:54:34
我最近在一个拆分字符串的地方碰到一个难题。
我有一个表的字段TaskID记录为
ExamTaskID='ZWRWS20060427001' and SampleID='ZW42060400001'
ExamTaskID='ZWRWS20060427001' and SampleID='ZW42060400002'
ExamTaskID='ZWRWS20060427001' and SampleID='ZW42060400003'
ExamTaskID='ZWRWS20060427002' and SampleID='ZW42060400001'
ExamTaskID='ZWRWS20060427002' and SampleID='ZW42060400002'
……
现在我想使用一个函数把这个字段拆分成
ExamTaskID SampleID ……………(这个表的其它不用拆分的字段)
'ZWRWS20060427001' 'ZW42060400001' ……
'ZWRWS20060427001' 'ZW42060400002' ……
'ZWRWS20060427001' 'ZW42060400003' ……
'ZWRWS20060427002' 'ZW42060400001' ……
'ZWRWS20060427002' 'ZW42060400002' ……
'ZWRWS20060427002' 'ZW42060400003' ……
也就是说拆分后的字段要跟表里面的其它字段显示,当然表有唯一主键ID
使用存储过程的做法,我已经实现,但是我现在想用函数实现,因为函数返回的数据集可以当作一个子查询进行使用,而存储过程不行。希望老大们能帮帮我!
上面的说明不知到描述清楚了没有,不清楚,我再补充。
...全文
247 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yujohny 2006-10-24
  • 打赏
  • 举报
回复
好了,就这样吧
该说的方法,邹老大,都说了,非常谢谢!
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
如果, 如果你一定要关联, 存储过程也是可以关联的, 通过openrowset调用存储过程, 这样就可以做到关联.

效率也是不太好.
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
效率确实不会太好. 因为要拆多次.

如果你用sql 2005了, 用xml处理就容易多了.

-- 下面这样就可以做到拆分(如果你的数据直接就是xml, 或者是符合xml标准的字符, 那处理起来连转换都省了)

SELECT tb.*,
ExamTaskID = B.TaskID.value('(/a/@ExamTaskID)[1]', 'varchar(50)'),
ExamTaskID = B.TaskID.value('(/a/@SampleID)[1]', 'varchar(50)'),
DataSn = B.TaskID.value('(/a/@DataSn)[1]', 'varchar(50)'),
ListNo = B.TaskID.value('(/a/@ListNo)[1]', 'varchar(50)')
FROM tb
OUTER APPLY(
SELECT TaskID = CONVERT(xml,
'<a ' + REPLACE(REPLACE(tb.TaskID, '''', '"'), ' and ', ' ') + '/>')
)B
yujohny 2006-10-24
  • 打赏
  • 举报
回复
我现在的做法就是存储过程,不过存储过程的执行语句,无法再当跟其它select语句连接使用、查询了。
因为可以写成一个函数,就可以通用的调用
现在行不通的话,那我就根据不同情况写不同的SQL来查询数据。
yujohny 2006-10-24
  • 打赏
  • 举报
回复
我也想过很久,感觉函数真的是无法实现了,所以才来找你帮忙。
不过你后面提的那个方案可以考虑使用,只能是没办法下的办法了
不知道这样拆分函数效率是否很差?
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
如果列名都不确定的话, 那用函数无法实现了, 因为函数无法实现动态确定列名, 只能用存储过程.


我的第2个函数稍微改一下, 能做到处理任意指定的列名, 但要动态确定出列名, 这不是函数能实现的了.

CREATE FUNCTION dbo.f_split2(
@TaskID varchar(100),
@fdname sysname)
RETURNS varchar(50)
AS
BEGIN
DECLARE @len int
SELECT @fdname = @fdname + '=''',
@len = LEN(@fdname)
IF CHARINDEX(@fdname, @TaskID) = 0
RETURN(NULL)
RETURN(
SUBSTRING(@TaskID,
CHARINDEX(@fdname, @TaskID) + @len,
CHARINDEX('''', @TaskID, CHARINDEX(@fdname, @TaskID) + @len)
- CHARINDEX(@fdname, @TaskID) - @len)
)
END
GO

SELECT *,
ExamTaskID = dbo.f_split2(TaskID, 'ExamTaskID'),
SampleID = dbo.f_split2(TaskID, 'SampleID'),
DataSn = dbo.f_split2(TaskID, 'DataSn'),
ListNo = dbo.f_split2(TaskID, 'ListNo')
FROM tb
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
字段名应该是可以确定的吧? 不然你怎么知道最终结果包含那些列?
yujohny 2006-10-24
  • 打赏
  • 举报
回复
哦,如果是这种特例的话,我就可以实现了
关键是拆分的字段都不能确定名字以及个数
难就在要先拆分字段,然后才能拆分值,依次插入记录
再与原来的表联合
yujohny 2006-10-24
  • 打赏
  • 举报
回复
好快的速度,一刷就回复了这么多,我试试
yujohny 2006-10-24
  • 打赏
  • 举报
回复
关键是这个字符串,有些是ListNo='LY1000000'
有些是
ExamTaskID='ZWRWS20060427005' and SampleID='ZW42060400091' and DataSn='0'
有些是
ExamTaskID = 'ZWRWS20060427006' AND SampleID = 'ZW42060400126'

虽然我在调用的时候,传入参数,查询出的就可能是相同规律的一种
但这就要求我必须是先拆分出字段来动态建立临时表##TempTable,
然后用游标来循环插入拆分的字段值,
这样函数又怎么返回呢?
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
当然

为了考虑通用性, 比如 ExamTaskID 可以在 SampleID 后面, 它们的值的长度可能是不固定的.
所以我的拆分处理写得有点复杂.

如果你的值如你列出的那么规范, 那么直接用 SUBSTRING 截取也就行了.
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
上面是我提到的两种方法的对应实现函数.
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
-- 示例数据
CREATE TABLE tb(
id int IDENTITY PRIMARY KEY,
TaskID varchar(100))
INSERT tb SELECT 'ExamTaskID=''ZWRWS20060427001'' and SampleID=''ZW42060400001'''
UNION ALL SELECT 'ExamTaskID=''ZWRWS20060427001'' and SampleID=''ZW42060400002'''
UNION ALL SELECT 'ExamTaskID=''ZWRWS20060427001'' and SampleID=''ZW42060400003'''
UNION ALL SELECT 'ExamTaskID=''ZWRWS20060427002'' and SampleID=''ZW42060400001'''
UNION ALL SELECT 'ExamTaskID=''ZWRWS20060427002'' and SampleID=''ZW42060400002'''
GO

-- 拆分函数1
CREATE FUNCTION dbo.f_split1()
RETURNS TABLE
AS
RETURN(
SELECT
id,
ExamTaskID = SUBSTRING(TaskID,
CHARINDEX('ExamTaskID=''', TaskID) + 12,
CHARINDEX('''', TaskID, CHARINDEX('ExamTaskID=''', TaskID) + 12)
- CHARINDEX('ExamTaskID=''', TaskID) - 12),
SampleID = SUBSTRING(TaskID,
CHARINDEX('SampleID=''', TaskID) + 10,
CHARINDEX('''', TaskID, CHARINDEX('SampleID=''', TaskID) + 10)
- CHARINDEX('SampleID=''', TaskID) - 10)
FROM tb
)
GO

-- 拆分函数2
CREATE FUNCTION dbo.f_split2(
@TaskID varchar(100),
@fdname sysname)
RETURNS varchar(50)
AS
BEGIN
DECLARE @len int
SELECT @fdname = @fdname + '=''',
@len = LEN(@fdname)
RETURN(
SUBSTRING(@TaskID,
CHARINDEX(@fdname, @TaskID) + @len,
CHARINDEX('''', @TaskID, CHARINDEX(@fdname, @TaskID) + @len)
- CHARINDEX(@fdname, @TaskID) - @len)
)
END
GO


-- 调用
SELECT *,
ExamTaskID = dbo.f_split2(TaskID, 'ExamTaskID'),
SampleID = dbo.f_split2(TaskID, 'SampleID')
FROM tb A, dbo.f_split1() B
WHERE A.id = B.id
GO

DROP TABLE tb
DROP FUNCTION dbo.f_split1, dbo.f_split2
yujohny 2006-10-24
  • 打赏
  • 举报
回复
SQL 2000
我试试你的方法
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
用函数可以返回一个表, 但这个表要和原始的表一起使用的话.
在2000中得这样:
方法1. 这个函数返回一个主键id, 和拆分的所有的字段的记录, 与原表关联查询
方法2. 这个函数针对某个值进行拆分, 通过参数决定拆分出那个值, 两次调用函数得到结果.
zjcxc 2006-10-24
  • 打赏
  • 举报
回复
你用的是什么版本的数据库?

22,199

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧