4

次のテーブルがあります。

EntryTag
---------
EntryID
TagID

putput の例 (EntryID、TagID):

1 2
1 4
1 5
2 3
2 4
2 5
etc...

Tags
----
TagID
Name

出力例:

1 peas
2 corn
3 carrots
...etc.

エントリごとにタグのリストを戻したいのですが、タグがカンマで区切られた 1 行として表示します。

たとえば、私はこれを見たいです:

EntryID     TagsCommaDelimited
-------     ------------------
1           corn, peas, carrots
2           barley, oats
...and so on 

したがって、各 EntryID をリストする必要があり、対応するタグのカンマ区切りのリストです。

そして、次のような Content テーブルから選択します。

Content
--------
ID   -(which is in essence the EntryID, they didn't make it consistent)
Description
..etc.

これが私が試したことですが、私の構文ではうまくいきません:

declare @tagsCommaDelimited varchar (200) 
set @tagsCommaDelimited = '';


With AllEntryTags_CTE(Name, EntryID )
as
(
    select Tags .Name,
           entryTags.EntryID 
    from  EntryTag entryTags
    join Tags on tags.Id = entryTags.TagID
    group by entryTags.EntryID, tags.Name, entryTags.TagID 
),

TagsByEntryCommaDelimited_CTE( EntryID, CommaDelimitedTags)
as
(
    select  distinct allTags.EntryID,
            (select @tagsCommaDelimited from ( select @tagsCommaDelimited = coalesce (case when @tagsCommaDelimited = '' then allTags.Name
                                                                                      else @tagsCommaDelimited + ',' + allTags.Name end ,'') as CommaDelimitedTags
    from  AllEntryTags_CTE allTags  
)

select EntryID, CommaDelimitedTags from TagsByEntryCommaDelimited_CTE

- - - - - - - - - - - - - -アップデート - - - - - - - - - - - ------------

今のところ、テストのために gotgn を使用しました

私が今抱えている問題は、最後のselectステートメントで最後のCTEを使用して、タグ名のコンマ区切りリストを取得しようとしていることです..しかし、構文が正しくないと言っています:

;WITH CommaDelimitedTagIDs AS
(
    SELECT DISTINCT EntryID,
    (SELECT SUBSTRING((SELECT ',' + CAST(TagID AS NVARCHAR(10)) 
                       FROM EntryTag AS T1 WHERE T1.EntryID=T2.EntryID 
                       ORDER BY TagID 
                       FOR XML PATH('')),2,200)) AS commaDelimitedTagIDs
    FROM EntryTag T2 
),

CommaDelimittedTagNames_CTE (EntryID, CommaDelimitedTagNames) as
( 
    SELECT EntryID, (SELECT SUBSTRING((SELECT ',' + Name 
                     FROM Tags 
                     WHERE commaDelimitedTagIDs LIKE '%'+CAST(ID AS NVARCHAR(5))+'%'  
                     ORDER BY ID FOR XML PATH('')),2,200) AS CSV) 
    FROM CommaDelimitedTagIDs
)

--select EntryID, CommaDelimitedTagNames from CommaDelimittedTagNames_CTE


SELECT  Title,
        [Description],
        DateSyndicated,
        DateUpdated,
        1, 
        CAST([Text] AS NVARCHAR(MAX)),
        Author,
        (select CommaDelimitedTagNames from CommaDelimittedTagNames_CTE) as tagNamesCommaDelimited 
 FROM Content
 Join CommaDelimittedTagNames_CTE tags on tags.EntryID = Content.ID
 group by ID, Title, [Description], 
          DateSyndicated, DateUpdated, 
          CAST(subtextContent.[Text] AS NVARCHAR(MAX)), Author 

この方法でも試してみましたが、運が悪い

  Select
    ....other fields
    (select CommaDelimitedTagNames from CommaDelimittedTagNames_CTE tagNames 
     join subContent on subContent.ID = tagNames.EntryID) as tags 
  FROM Content as subContent

わかりました。結合できないと思います。Where に変更する必要がありました。理由はわかりませんが、これは現在機能しています:

   Select
    ....other fields
    (select CommaDelimitedTagNames from CommaDelimittedTagNames_CTE tagNames 
     where Content.ID = tagNames.EntryID) as tags 
  FROM Content 
4

2 に答える 2

14
select ET1.EntryID,
       (
       select ', '+T.Name
       from Tags as T
         inner join EntryTag as ET2
           on T.TagID = ET2.TagID
       where ET1.EntryID = ET2.EntryID
       for xml path(''), type
       ).value('substring(text()[1], 3)', 'varchar(max)') as TagsCommaDelimited
from EntryTag as ET1
group by ET1.EntryID

クエリの分析

メインクエリは aを実行するgroup byため、各 に対して 1 つの行のみを取得しますEntryID

TagsCommaDelimited相関サブクエリを使用して列が作成されます。

SQL Server ではfor xml path、クエリ結果の XML 表現を作成するために使用されます。path列の別名とおよびへのパラメーターを使用して、XML の作成方法を適切に制御できますroot

', '+T.Name相関サブクエリの連結された値には列名がなく、空のパラメーターfor xml path('')はタグなしで xml を作成します。返されるテキスト値は 1 つだけです。

クエリに追加typeすると、データ型は になります。for xmlXML

XML から値を取得するには、value()メソッドを使用する必要があります。文字列にキャストすることもできますが、それを行うと、たとえば、&使用した場所のどこにでも文字列が入ります&

関数の最初のパラメーターvalue()は、必要な値を取得するために使用される xQuery 式です。text()現在の要素の値のみが必要であることを指定するために使用します。[1]は、最初のテキスト ノードを見つけたい (ここでは 1 つしかありません) ことを SQL Server に伝えていますが、それでも必要です。

クエリによって作成された文字for xml列には、文字列の先頭に余分なコンマとスペースがあり、削除する必要があります。ここでは、XQuery 関数を使用してsubstring、最初の 2 文字以外のすべてを取得します。

2 番目のパラメーターvalue()は、返されるデータ型を指定します。

于 2013-01-17T07:49:53.653 に答える
1
DECLARE @TableOne TABLE
(
    EntryID INT,
    TagID INT
)

DECLARE @TableTwo TABLE
(
    TagID INT,
    Name NVARCHAR(100)
)

INSERT INTO @TableOne (EntryID,TagID)
VALUES  (1,2)
       ,(1,4)
       ,(1,5)
       ,(2,3)
       ,(2,4)
       ,(2,1)

INSERT INTO @TableTwo (TagID,Name)
VALUES  (1,'Daniel')
       ,(2,'Samuel')
       ,(3,'Petkov')
       ,(4,'Ivan')
       ,(5,'Jack')

/* 
    In this CTE we are going to format the values int the folowing way:

    1   2,4,5
    2   1,3,4

    Or for eaech EntryIDs, we will have all its TagIDs 

*/
;WITH CTE AS
(
    SELECT DISTINCT EntryID
          ,(SELECT SUBSTRING((SELECT ',' + CAST(TagID AS NVARCHAR(10)) FROM @TableOne AS T1 WHERE T1.EntryID=T2.EntryID ORDER BY TagID FOR XML PATH('')),2,200)) AS CSVTags
    FROM @TableOne T2

)
/*
    Here we are replacing the EntryIDs with their names from the @TableTwo:
*/
SELECT EntryID
      ,(SELECT SUBSTRING((SELECT ',' + Name FROM @TableTwo WHERE CSVTags LIKE '%'+CAST(TagID AS NVARCHAR(5))+'%' ORDER BY TagID FOR XML PATH('')),2,200) AS CSV) 
FROM CTE
于 2013-01-17T08:20:38.027 に答える