すべてのタグを含むすべての投稿を選択

.net c# dapper sql sql-server

質問

これについて多くの質問がありますが、特に私がこの場合に使用しているSQL Serverを使用して、決定的な回答が不十分です。

私はそれに関連するブログ投稿とタグを表す3つのテーブルを持っています。すべての投稿と各投稿タグを取得するクエリを実行したい - タグIDと名前の両方が必要です。その結果は、私のC#クラスに簡単にシリアライズ可能である必要があります。私もDapper.netを使用しようとしていますが、それは最も重要な部分ではありません。

明らかに多くのウェブサイトでこれが行われています。私は最良の方法と、実際の世界でどのように行うべきかを知りたいですか?すべての投稿を取得した後、それぞれの投稿ごとに複数のクエリを実行すると、各投稿のタグが返されます。しかし確かに良い方法があるはずですか?

もし私がちょうど1つの投稿を取得しようとしていたなら、私は複数の選択肢を書きます。 1つは投稿用、もう1つはタグ用です。しかし、私はすべての投稿が欲しい。返される各タグ行の投稿情報を複製せずにこれを行う方法はありますか?

各投稿のタグが、たとえばコンマで区切られた列にシリアル化されている場合、IDと名前の両方を取得するにはどうすればよいでしょうか?文字列をエンコードしますか?

SELECT * FROM dbo.Posts    
SELECT * FROM dbo.Tags
SELECT * FROM dbo.PostTags

Posts
Id  Title       Content
===============================
1   First Post  First Content
3   Second      Second Content

Tags
Id  Name
============
1   C#
2   SQL
3   IIS
4   Steam
5   OpenID

PostTags
PostId  TagId
=============
1       1
1       2
3       3
3       4

次のクエリでテーブルを結合するだけです。

SELECT p.*, t.Name
FROM dbo.Posts p
LEFT JOIN dbo.PostTags pt ON p.id = pt.PostId
LEFT JOIN dbo.Tags t ON t.id = pt.TagId

関連する各タグの投稿コンテンツを繰り返すことで、多くの冗長なデータを提供します。

Id  Title       Content         Name
======================================
1   First Post  First Post      C#
1   First Post  First Post      SQL
3   Second Post Second Content  IIS
3   Second Post Second Content  Steam

人気のある回答

これは純粋に練習であり、重複しているデータの量は大したことではない可能性が高いと言います。ポストのサイズが非常に大きく、それらのポストがたくさんある場合、重複を避けるためにはより意味をなさないようになります。

さらに、C#Linq-to-SqlまたはEntity Frameworkを使用すると、オブジェクトの関係が作成され、 Postエンティティはアクセス可能なList<Tag>プロパティを持ちます。

しかし、あなた自身のタイプのものをロールしたい場合は、1回のDBラウンドトリップとデータの重複を伴​​わない1つのオプションは、2つのレコードセット(2つの別々のselectステートメント)を返すストアドプロシージャを書くことです。 1つはタグの内容です。

それで、 Postを表すC#クラスを作成するのはかなりシンプルで、 List<Tag>あり、それをストアドプロシージャの結果から取得するだけです。

Create Procedure GetPostTags
As

-- We will use the GotTags column here to loop through and get tabs later
Declare @Posts Table (
    PostID varchar(50), 
    PostTitle varchar(50), 
    PostContent varchar(50),
    GotTags bit default 0
)

/* Assuming you care about the ID's, this will get you all of 
   the tags without duplicating any post content */
Declare @PostTags Table (
    PostID int,
    TagID int,
    TagName varchar(50)
)

-- Populate posts from the main table
Insert Into @Posts (PostID, PostTitle, PostContent)
Select * From Posts

-- Now loop through and get the tags for each post. 
Declare @CurrentPostID int
Set @CurrentPostID = (Select Top 1 PostID From @Posts Where GotTags = 0)
While @CurrentPostID Is Not Null
    Begin
        Insert Into @PostTags (PostId, TagID, TagName)
        Select pt.postid, pt.tagid, t.name
        From Tags t 
            Join PostTags pt
                On t.id = pt.tagid
        Where pt.postid = @CurrentPostID

        -- Set next loop
        Update @Posts Set GotTags = 1 Where PostID = @CurrentPostID
        Set @CurrentPostID = (Select Top 1 PostID From @Posts Where GotTags = 0)
    End

-- Return 2 recordsets, which are related by the PostID column found in both sets
Select * from @Posts
Select * From @PostTags

私は文字列を1つの文字列に連結し、後でそれらを分割するよりも、このタイプのソリューションを好む。この方法でデータを扱うのが容易になり、C#でよりオブジェクト指向になり、タグを削除したりポストから追加したりする必要がある場合に、タグIDの追跡が容易になります。既にIDを持っているので、名前でタグやマッチを見つけることができます。



ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ