Лучше всего было бы нормализовать ваши таблицы, поэтому TableA будет иметь одну строку на данные Col2. Вы могли бы присоединиться к столам очень легко и быстро. Wihtout делая это, вы можете попробовать следующее:
Перед тем, как использовать свою функцию, необходимо создать «вспомогательный» стол, вам нужно только сделать это один раз для каждой базы данных:
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 @[email protected]+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
EDIT
дать этому попытку, это может быть быстрее:
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
Возможно, мне придется нормализовать TableA. Таблица имеет более 3000 строк, и хотя ваша функция работает, она медленная. Если бы я нормализовал таблицу, не могли бы вы показать мне sql для этого? Спасибо – 2009-08-24 20:59:42
Спасибо. Это отлично. – 2009-08-24 22:27:59