我有两张桌子。一个有2列 - ID,标签。标签列是标记值的逗号分隔列表。
我在第二张表中,还有两列。一个是标签列表,每个标签都在自己的行中,第二列是该标签的标签。
我需要做的是为每个ID创建一个输出查询,每个ID都有一个以分号分隔的标签标签列表,每个ID在其列表中都有相应的标签值。
以下是两个表的简短示例:
Table1 -
ID---Tags
1---tag1,tag2,tag3,tag6
2---tag2,tag4,tag5
3---tag3,tag8,tag9,tag10
4---tag1,tag2,tag6
5---tag1,tag4,tag5
Table2 -
tagname---taglabel
tag1--- Nice Name Tag1
tag2--- Nice Name Tag2
tag3--- Nice Name Tag3
tag4--- Nice Name Tag4
tag5--- Nice Name Tag5
tag6--- Nice Name Tag6
tag7--- Nice Name Tag7
tag8--- Nice Name Tag8
tag9--- Nice Name Tag9
tag10--- Nice Name Tag10
期望的结果集 -
ID---TagsNames
1---Nice Name Tag1,Nice Name Tag2,Nice Name Tag3,Nice Name Tag6
2---Nice Name Tag2,Nice Name Tag4,Nice Name Tag5
3---Nice Name Tag3,Nice Name Tag8,Nice Name Tag9,Nice Name Tag10
4---Nice Name Tag1,Nice Name Tag2,Nice Name Tag6
5---Nice Name Tag1,Nice Name Tag4,Nice Name Tag5
我尝试为初始连接设置查询,认为我可以获取结果集并连接行,但我似乎无法使部分连接起作用。这是查询:
SELECT gt.id as g
,gt.tags as tg
,tt.HitTagName as ht
,tt.termlabel as tl
FROM tblidtags gt (nolock)
JOIN tbltaglabels tt (Nolock) ON gt.tg like '%' + tt.ht + '%'
非常感谢任何建议!
答案 0 :(得分:1)
首先,如果你可以,normalize表而不是多值列。这是一个糟糕的数据库设计,很难查询,正如您将看到的那样。
现在,如果您真的无法修改数据库架构,请执行以下操作:
tag1,tag2,tag3
为三行; Table2
; 以下是生成的查询和正常工作 sqlfiddle:
WITH tmp (id, tag, tags) AS (
SELECT id, LEFT(tags, CHARINDEX(',',tags+',')-1),
STUFF(tags, 1, CHARINDEX(',',tags+','), '')
FROM tbl1
UNION ALL
SELECT id, LEFT(tags, CHARINDEX(',',tags+',')-1),
STUFF(tags, 1, CHARINDEX(',',tags+','), '')
FROM tmp
WHERE tag > ''
)
SELECT id,
STUFF((SELECT ',' + tbl2.descr FROM tmp INNER JOIN tbl2 ON (tmp.tag = tbl2.tag)
WHERE id = a.id
FOR XML PATH ('')), 1, 1, '') tag_names
FROM tmp a
WHERE tag != ''
GROUP BY id
ORDER BY id;
要规范化架构,您需要创建一个中间表,例如id_tag(id, tag)
,其中(id, tag)
将构成主键。然后,您可以使用上述查询的第一部分(tmp
表)来填充此表。在此之后,您可以删除Table1
。
答案 1 :(得分:1)
;WITH cte AS (
SELECT a.ID, b.taglabel FROM
(SELECT c.ID, Split.a.value('.', 'VARCHAR(100)') AS Tags FROM
(SELECT ID, CAST('<M>' + REPLACE(Tags, ',' , '</M><M>') + '</M>' AS XML) AS Tag
FROM dbo.Table1) c
CROSS APPLY Tag.nodes('/M') Split(a)) a
LEFT JOIN dbo.Table2 b ON b.tagname = a.Tags)
SELECT ID, STUFF(
(SELECT DISTINCT ',' + NULLIF(taglabel,'') FROM cte t2
WHERE t1.id = t2.id FOR XML PATH(''), TYPE).value('.','VARCHAR(MAX)'),1,2,'') AS tags
FROM cte t1 GROUP BY ID ORDER BY ID
CREATE TABLE dbo.Table1 (
ID tinyint PRIMARY KEY,
Tags varchar(25))
CREATE TABLE dbo.Table2(
tagname varchar(5) PRIMARY KEY,
taglabel varchar(15))
INSERT INTO dbo.Table1 VALUES
(1, 'tag1,tag2,tag3,tag6'),
(2, 'tag2,tag4,tag5'),
(3, 'tag3,tag8,tag9,tag10'),
(4, 'tag1,tag2,tag6'),
(5, 'tag1,tag4,tag5')
INSERT INTO dbo.Table2 VALUES
('tag1', 'Nice Name Tag1'),
('tag2', 'Nice Name Tag2'),
('tag3', 'Nice Name Tag3'),
('tag4', 'Nice Name Tag4'),
('tag5', 'Nice Name Tag5'),
('tag6', 'Nice Name Tag6'),
('tag7', 'Nice Name Tag7'),
('tag8', 'Nice Name Tag8'),
('tag9', 'Nice Name Tag9'),
('tag10', 'Nice Name Tag10')
ID tags ---- ------------------------------------------------------------------ 1 Nice Name Tag1,Nice Name Tag2,Nice Name Tag3,Nice Name Tag6 2 Nice Name Tag2,Nice Name Tag4,Nice Name Tag5 3 Nice Name Tag10,Nice Name Tag3,Nice Name Tag8,Nice Name Tag9 4 Nice Name Tag1,Nice Name Tag2,Nice Name Tag6 5 Nice Name Tag1,Nice Name Tag4,Nice Name Tag5
要标准化,请创建另一个表:
CREATE TABLE tags (
id mediumint,
tag varchar(5),
PRIMARY KEY (id, tag))
INSERT INTO tags (id, tag) VALUES
SELECT c.ID, Split.a.value('.', 'VARCHAR(100)') AS Tags FROM
(SELECT ID, CAST('<M>' + REPLACE(Tags, ',' , '</M><M>') + '</M>' AS XML) AS Tag
FROM dbo.Table1) c
CROSS APPLY Tag.nodes('/M') Split(a)
然后,您可以JOIN
tags
tag
上的{{1}}。
查看this小提琴,了解规范化架构的外观。