使用SQL2000将字段中的数据拆分为行

时间:2010-07-11 02:28:59

标签: sql sql-server-2000

请帮我找一个解决方案。我有像

这样的表格中的数据
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 个答案:

答案 0 :(得分:3)

我的第一个建议是规范化您的数据库。列应包含单条信息。您的逗号分隔值违反了此规则,这就是您遇到此类困难的原因。虽然人们很少接受这个建议,但这里有一个可能对你有用的kludge。由于您将此连接到另一个表,因此您不需要在其自己的列中分离每个值,您只需要能够在列中找到匹配的值:

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 :(得分:1)

答案是规范化您的数据库。

与此同时,在大型集合上表现更好的解决方法是使用临时表。 (LIKE搜索不能使用索引)

此方法还显示了规范化数据和处理空格的一些步骤。

如果您没有"Tally Table",请先创建all这是一次性交易,Tally表可以派上用场kinds {{3} } things

/*--- 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