1

我有两张桌子。一列有 2 列 - 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 + '%'

任何建议都非常感谢!

4

2 回答 2

1

首先,如果可以的话,规范化表格而不是多值列。这是糟糕的数据库设计,很难查询,接下来您将看到。

现在,如果您真的无法修改数据库模式,那么您必须执行以下操作:

  1. 将每个多值列转换为行,即tag1,tag2,tag3转换为三行;
  2. 对于每一行,从Table2;中获取其描述。
  3. 最后,连接所有描述,按 id 分组。

这是生成的查询和有效的 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.

于 2012-08-20T15:33:33.123 回答
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')

结果

身份标签
---- ---------------------------------------------- --------------------
1 好名牌1,好名牌2,好名牌3,好名牌6
2 好名牌2,好名牌4,好名牌5
3 好名牌10,好名牌3,好名牌8,好名牌9
4 好名字标签1,好名字标签2,好名字标签6
5 好名牌1,好名牌4,好名牌5

编辑 1

要规范化,请创建另一个表,如下所示:

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)

然后,您可以JOINtags每个tag.

编辑 2

看看这个小提琴,看看标准化模式的外观。

于 2012-08-20T15:37:54.930 回答