2009-08-24 2 views
2

У меня есть таблица со строковыми значениями, которые должны быть индивидуально сопоставлены столбцу. НапримерСравнение строковых данных с данными таблицы

Таблица 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 

мне нужно, чтобы быть в состоянии соответствовать и тянуть записей из таблицы A.Col1 для матча на TableA.col2 = TableB.col1

СКП приводится ниже:

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 

ответ

2

Лучше всего было бы нормализовать ваши таблицы, поэтому 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

+0

Возможно, мне придется нормализовать TableA. Таблица имеет более 3000 строк, и хотя ваша функция работает, она медленная. Если бы я нормализовал таблицу, не могли бы вы показать мне sql для этого? Спасибо – 2009-08-24 20:59:42

+0

Спасибо. Это отлично. – 2009-08-24 22:27:59

0

Вы можете нормализовать таблицу с col2 значения, так что это больше похоже на:

Col1 col2 
1234 0029QS 
1234 0029QT 
1234 0029QU 
1234 0029QV 
2222 0006AG_0042 
2343 0032BP 
2343 0032BQ 
2343 0032BR 

Затем вы можете сделать внутреннее соединение по col2 и таблице б

Смежные вопросы