SQL查询中的左连接问题

SQL查询中的左连接问题,sql,sql-server,left-join,Sql,Sql Server,Left Join,我有三个表Post,PostTagMap和TagPostTagMap是一个连接表,用于映射具有多个标记的单个post我正在尝试编写一个查询,以提取属于某个标记名的所有帖子 Post表 Id Name 1 Post #1 2 Post #2 Id Name 1 JS 2 CSS Id PostId TagId 1 1 1 2 1 2 标记表 Id Name 1 Pos

我有三个表
Post
PostTagMap
Tag
PostTagMap
是一个连接表,用于映射具有多个标记的单个post我正在尝试编写一个查询,以提取属于某个标记名的所有帖子

Post表

Id    Name

1     Post #1

2     Post #2
Id   Name

1     JS

2     CSS
Id   PostId   TagId

1       1       1
2       1       2

标记表

Id    Name

1     Post #1

2     Post #2
Id   Name

1     JS

2     CSS
Id   PostId   TagId

1       1       1
2       1       2

PostTagMap表

Id    Name

1     Post #1

2     Post #2
Id   Name

1     JS

2     CSS
Id   PostId   TagId

1       1       1
2       1       2
(已编辑PostTagMap数据以与问题相匹配)


@Tag
NULL
时,我只获取post id 1的详细信息,而不是2的详细信息。上述查询有什么问题

下面也试过了

SELECT P.Id FROM Post P
LEFT JOIN PostTagMap PTM ON P.Id = PTM.PostId
LEFT JOIN Tag T ON PTM.TagId = T.Id
WHERE T.Name = ISNULL(@Tag, T.Name)
以上还未回复帖子详情2条

SELECT P.Id FROM Post P
LEFT JOIN PostTagMap PTM ON P.Id = PTM.PostId
LEFT JOIN Tag T ON PTM.TagId = T.Id AND T.Name = ISNULL(@Tag, T.Name)

返回所有内容,甚至将@Tag作为“JS”传递。

我尝试了您的所有查询,但都可以正常工作,试试这个

每个查询都像它应该的那样工作,也许问题不在于查询

SELECT P.Id FROM Post P
LEFT JOIN PostTagMap PTM ON P.Id = PTM.PostId
INNER JOIN Tag T ON PTM.TagId = T.Id
WHERE T.Name = ISNULL('Css', T.Name)
按预期仅返回Post 1,而不是所有内容

编辑:

我理解你的问题,现在试试我的问题

DECLARE @Tag NVARCHAR(50)
set @Tag = NULL

SELECT P.Id FROM Post P
LEFT JOIN PostTagMap PTM ON P.Id = PTM.PostId
LEFT JOIN Tag T ON PTM.TagId = T.Id
WHERE @Tag IS NULL OR T.Name = @Tag
GROUP BY P.Id
选择所有
Post
,然后添加
其中@Tag为NULL
,以防您的
@Tag
为NULL,而其他为
T。Name=@Tag
希望它能帮助您运行:

SELECT P.Id FROM Post P
LEFT JOIN PostTagMap PTM ON P.Id = PTM.PostId
LEFT JOIN Tag T ON PTM.TagId = T.Id
WHERE T.Name = COALESCE(@Tag, T.Name)
当@Tag为NULL时,它将返回所有内容。 我不知道这是否是你所期望的


这里是我的

,因为您使用左连接来连接依赖于
@Tag
条件的行,所以您基本上从不过滤
Post
记录,您总是得到所有记录

确实,如果存在匹配的行,您正在从左侧联接的表中选择其他数据,但这并不影响返回的
Post
记录

您需要做的是:
如果@Tag为空-不要过滤。
否则-应用过滤器,并使用内部连接执行此操作:

你的问题是

WHERE T.Name = ISNULL(@Tag, T.Name)
因为当
T.Name为NULL时,
T.Name=T.Name
为FALSE

在中更改where子句

WHERE (T.Name = @Tag) or (@Tag IS NULL)

同时使用
左联接
或内部联接将筛选出联接表中没有条目的行

您的内部联接也将在内部联接中旋转您的左联接。将
移动到
的位置
并使其成为
上的
的一部分,当@Tag为NULL时,它应该返回所有正确的内容吗?但它只会在1后返回,我认为你是对的。在小提琴上演奏得很好。问题可能是别的。你可以试着在我的提琴中将“Css”改为NULL,它将返回每个帖子。我注意到,在你的提琴中,两篇帖子都有映射到它的标签。在我的例子中,第二篇文章没有任何标签。编辑我的答案并在你的小提琴中尝试当@Tag为空时,它不会返回帖子2详细信息当你设置@Tag='Js'时,它会返回两篇文章,但它应该只返回帖子1完全重写我的答案,做了一些测试,这很有效。