1

私は2つのテーブルを持っています。ID、タグの 2 つの列があります。tags 列は、タグ値のコンマ区切りリストです。

2 番目のテーブルには、2 つの列もあります。1 つはタグのリストで、それぞれが独自の行にあり、2 番目の列はそのタグのラベルです。

私がする必要があるのは、リストに対応するタグ値を持つ ID ごとに、セミコロンで区切られたタグ ラベルのリストを使用して、各 ID の出力クエリを作成することです。

2 つのテーブルの短い例を次に示します。

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,tag33 つの行に変換します。
  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')

結果

IDタグ
---- -------------------------------------------------- --------------------
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)

JOINその後、tagsそれぞれにアクセスできますtag

編集 2

このフィドルを見て、正規化されたスキーマがどのように見えるかを確認してください。

于 2012-08-20T15:37:54.930 に答える