2010-07-11 41 views
0

请帮我找到一个解决方案。我有一个像使用SQL2000将字段中的数据拆分为行

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列中的值加入另一个表中的另一列。 感谢您的支持

回答

3

我的第一个建议是规范化您的数据库。一列应包含一条信息。你的逗号分隔的值违反了这个规则,这就是为什么你面临这样的困难。因为人们很少会采纳这个建议,这里有一个可能适合你的混合物。既然你加入这个到另一个表,你并不真的需要每个值在自己的列分离出来,你只需要能够找到在你列一个匹配值:

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

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

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

该方法还显示了标准化数据和处理空白的一些步骤。

如果您没有,请先创建一个"Tally Table"这是一次性交易,Tally表格适用于allkindsthings

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