Сравните строковые данные с табличными данными - PullRequest
2 голосов
/ 24 августа 2009

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

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

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

Ответы [ 2 ]

2 голосов
/ 24 августа 2009

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

OUTPUT

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 голосов
/ 24 августа 2009

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

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

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

.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...