关于这个有很多问题,但没有足够明确的答案,尤其是在这种情况下使用 SQL Server。
我有 3 个表来表示博客文章和与之关联的标签。我想运行一个查询来获取所有帖子和每个帖子标签——我需要标签 ID 和名称。结果需要很容易序列化到我的 C# 类中。我也在尝试使用 Dapper.net 但这不是最重要的部分。
显然很多网站都这样做,我想知道最好的方法以及在现实世界中应该如何做?我可以获得所有帖子,然后对每个帖子运行多个查询,然后返回每个帖子的标签。但肯定有更好的方法吗?
如果我只是想获得一个帖子,那么我会写多个选择。一个用于帖子,一个用于标签。但我想要所有的帖子。有没有一种方法可以在不为返回的每个标签行复制发布信息的情况下执行此操作?
例如,如果每个帖子的标签都序列化到一个以逗号分隔的列中,那么如何才能同时获得 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>
您可以访问的属性。
但是,如果您想滚动自己的类型,一个只涉及一次数据库往返且不重复数据的选项是编写一个存储过程,让您返回 2 个记录集(2 个单独的选择语句)- 一个带有发布内容,一个带标签的内容。
然后创建一个表示 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
我更喜欢这种类型的解决方案,而不是将字符串连接成一个字符串,然后再将它们拆分;它使以这种方式处理数据变得更容易,允许在 C# 中更加面向对象,并且让您更容易跟踪标签 ID,以防标签需要从帖子中删除或添加,您不需要查找标签或按名称匹配,因为您已经有了 ID。
关于c# - 选择所有带有所有标签的帖子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21767613/