请帮我找一个解决方案。我有像
这样的表格中的数据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列中的值来连接另一个表中的另一列。 感谢您的支持
答案 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