我有一个包含字符串值的表,需要单独匹配一列。例如
表A
Col1 col2
1234 0029QS, 0029QT, 0029QU, 0029QV
2222 0006AG_0042
2343 0032BP, 0032BQ, 0032BR
1232 5000_0708, 5000_0709, 5000_0710
表B
0029QS
0032BQ
0006AG_0042
5000_0709
我需要能够匹配并从Table A.Col1中提取记录以获得TableA.col2 = TableB.col1
的匹配sql如下:
Create Table TableA(Col1 int , Col2 varchar(max) )
INSERT INTO TableA
Select 1234, '029QS, 0029QT, 0029QU, 0029QV'
INSERT INTO TableA
Select 2222, '0006AG_0042'
INSERT INTO TableA
Select 2343, '0032BP, 0032BQ, 0032BR'
INSERT INTO TableA
Select 1232, '5000_0708, 5000_0709, 5000_0710'
Go
Create table TableB(Col2 Varhcar(50) )
INSERT INTO TableB
Select '0029QS'
INSERT INTO TableB
Select '0032BQ'
INSERT INTO TableB
Select '0006AG_0042'
INSERT INTO TableB
Select '5000_0709'
INSERT INTO TableB
Select '5000_0710'
GO
答案 0 :(得分:2)
您最好的选择是规范化表格,因此TableA每个Col2数据会有一行。然后,您可以非常轻松快速地加入表格。如果不这样做,您可以尝试以下方法:
在使用我的功能之前,您需要设置一个“帮助程序”表,每个数据库只需执行一次这样的操作:
CREATE TABLE Numbers
(Number int NOT NULL,
CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
DECLARE @x int
SET @x=0
WHILE @x<8000
BEGIN
SET @x=@x+1
INSERT INTO Numbers VALUES (@x)
END
使用此函数来分割您的字符串,该字符串不会循环且非常快:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
@SplitOn char(1) --REQUIRED, the character to split the @List string on
,@List varchar(8000) --REQUIRED, the list to split apart
)
RETURNS
@ParsedList table
(
ListValue varchar(500)
)
AS
BEGIN
/**
Takes the given @List string and splits it apart based on the given @SplitOn character.
A table is returned, one row per split item, with a column name "ListValue".
This function workes for fixed or variable lenght items.
Empty and null items will not be included in the results set.
Returns a table, one row per item in the list, with a column name "ListValue"
EXAMPLE:
----------
SELECT * FROM dbo.FN_ListToTable(',','1,12,123,1234,54321,6,A,*,|||,,,,B')
returns:
ListValue
-----------
1
12
123
1234
54321
6
A
*
|||
B
(10 row(s) affected)
**/
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
INSERT INTO @ParsedList
(ListValue)
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = @SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
RETURN
END --Function FN_ListToTable
您可以在此查询中使用此功能来解决您的问题......
select
a.Col1,b.Col2,a.Col2,b.Col2
FROM TableA a
INNER JOIN TableB b On b.Col2 IN (SELECT ListValue FROM dbo.FN_ListToTable(',',a.Col2))
输出
Col1 Col2 Col2
----------- ------------- -------------------------------
2222 0006AG_0042 0006AG_0042
2343 0032BQ 0032BP, 0032BQ, 0032BR
1232 5000_0709 5000_0708, 5000_0709, 5000_0710
1232 5000_0710 5000_0708, 5000_0709, 5000_0710
修改强>
尝试一下,它可能会更快:
select
a.Col1,b.Col2,a.Col2
FROM TableA a
CROSS APPLY dbo.FN_ListToTable(',',a.Col2) a2
INNER JOIN TableB b On a2.ListValue=b.Col2
如果要标准化表格,请执行以下操作:
Create Table TableA2(Col1 int , Col2 varchar(50) )
不要忘记在Col2上创建索引
INSERT INTO TableA2
SELECT
a.Col1, b.ListValue
FROM TableA a
CROSS APPLY dbo.FN_ListToTable(',',a.Col2) b
现在找到匹配项:
SELECT
a.*
FROM TableA2 a
INNER JOIN TableB b ON a.Col2=b.Col2
完成更改,如果需要,可以删除TableA表,然后将TableA2重命名为TableA
答案 1 :(得分:0)
您可以使用col2值对表进行规范化,因此它更像是:
Col1 col2
1234 0029QS
1234 0029QT
1234 0029QU
1234 0029QV
2222 0006AG_0042
2343 0032BP
2343 0032BQ
2343 0032BR
然后你可以在col2和table b上进行内连接