разбить данные в поле на строку, используя SQL2000 - PullRequest
0 голосов
/ 11 июля 2010

Пожалуйста, помогите мне найти решение.У меня есть данные в таблице, такие как

ID    Code      

1     123,456,789,12  
2     456,073          
3     69,76,56

Мне нужен список кода в строке

ID    Code                 Ref

1     123,456,789,12       123

1     123,456,789,12       456

1     123,456,789,12       789

1     123,456,789,12       12

2     456,073              456

2     456,073              073

3     69,76,56             69

3     69,76,56             76

3     69,76,56             56

Как мне это сделать в команде запроса?Я буду использовать значение в столбце ref, чтобы объединить другой столбец в другой таблице.Спасибо за поддержку

Ответы [ 2 ]

3 голосов
/ 11 июля 2010

Мой первый совет - нормализовать вашу базу данных. Столбец должен содержать один фрагмент информации. Ваши значения, разделенные запятыми, нарушают это правило, поэтому вы сталкиваетесь с такой сложностью. Хотя люди редко когда-либо принимают этот совет, вот клудж, который может сработать для вас. Поскольку вы присоединяете это к другой таблице, вам не нужно выделять каждое значение в отдельном столбце, вам просто нужно найти соответствующее значение в вашем столбце:

SELECT
    T1.id,
    T1.code,
    T2.ref
FROM
    My_Table T1
INNER JOIN Table_I_Am_Joining T2 ON
    T1.code LIKE '%,' + CAST(T2.ref AS VARCHAR(20)) + ',%' OR
    T1.code LIKE CAST(T2.ref AS VARCHAR(20)) + ',%' OR
    T1.code LIKE '%,' + CAST(T2.ref AS VARCHAR(20)) OR
    T1.code = CAST(T2.ref AS VARCHAR(20))

Это зависит от кодов в вашем столбце, которые должны быть в точном формате, разделенном запятыми без пробелов. Если это не так, то, скорее всего, это не вернет то, что вы пытаетесь получить.

1 голос
/ 11 июля 2010

Ответ заключается в нормализации вашей базы данных.

Тем временем, обходной путь, который будет работать лучше на больших наборах, заключается в использовании временной таблицы. (LIKE поиск не может использовать индекс)

Этот подход также показывает некоторые шаги к нормализации данных и обрабатывает пробелы.

Сначала создайте «Таблица подсчета» , если у вас ее нет. Это разовая сделка, и таблицы подсчета пригодятся для все виды из вещи .

/*--- Create a Tally table.  This only needs to be done once.
    Note that "Master.dbo.SysColumns" is in all SQL 2000 installations.
    For SQL 2005, or later, use "master.sys.all_columns".
*/
SELECT TOP 11000   -- Adequate for most business purposes.
    IDENTITY (INT, 1, 1)    AS N
INTO
    dbo.Tally
FROM
    Master.dbo.SysColumns sc1,
    Master.dbo.SysColumns sc2

--- Add a Primary Key to maximize performance.
ALTER TABLE     dbo.Tally
ADD CONSTRAINT  PK_Tally_N PRIMARY KEY CLUSTERED (N) WITH FILLFACTOR = 100

Теперь предположим, что ваши таблицы:

CREATE TABLE ListO_Codes (ID INT IDENTITY(1,1), Code VARCHAR(88))

INSERT INTO ListO_Codes (Code)
SELECT      '123,456,789,12'        UNION ALL
SELECT      '456,073'               UNION ALL
SELECT      '69,76,56'


CREATE TABLE AnotherTable (ID INT IDENTITY(1,1), Ref VARCHAR(8), CodeWord VARCHAR (88))

INSERT INTO AnotherTable (Ref, CodeWord)
SELECT      '12',   'Children'      UNION ALL
SELECT      '123',  'of'            UNION ALL
SELECT      '456',  '-'             UNION ALL
SELECT      '789',  'sun,'          UNION ALL
SELECT      '073',  'see'           UNION ALL
SELECT      '56',   'your'          UNION ALL
SELECT      '69',   'time'          UNION ALL
SELECT      '76',   'has'

Тогда временная таблица:

CREATE TABLE    #NORMALIZED_Data (LOD_id INT, Ref int)  -- Make Ref varchar if it's not numeric
INSERT INTO
    #NORMALIZED_Data (LOD_id, Ref)
SELECT
    L.ID,
    -- Split Code string using Tally table and Delimiters
    LTrim (RTrim (SUBSTRING (',' + L.Code + ',', T.N+1, CHARINDEX (',', ',' + L.Code + ',', T.N+1) - T.N - 1 ) ) )
FROM
    dbo.Tally       T,
    ListO_Codes     L
WHERE
    T.N < LEN (',' + L.Code + ',')
AND
    SUBSTRING (',' + L.Code + ',', T.N, 1)   = ','


--- Index for performance
CREATE CLUSTERED INDEX CL_NORMALIZED_Data_LOD_id_Ref
ON #NORMALIZED_Data (LOD_id, Ref) WITH FILLFACTOR = 100

Тогда поиск будет:

SELECT
    L.ID,
    L.Code,
    A.Ref,
    A.CodeWord
FROM
    #NORMALIZED_Data    N
INNER JOIN
    ListO_Codes         L   ON N.LOD_id = L.ID
LEFT JOIN
    AnotherTable        A   ON N.Ref    = A.Ref
ORDER BY
    L.ID,
    A.Ref

И результаты:

ID    Code              Ref    CodeWord
--    --------------    ---    --------
1     123,456,789,12    12     Children
1     123,456,789,12    123    of
1     123,456,789,12    456    -
1     123,456,789,12    789    sun,
2     456,073           073    see
2     456,073           456    -
3     69,76,56          56     your
3     69,76,56          69     time
3     69,76,56          76     has
...