SQL查询中的左连接问题

时间:2018-05-03 07:18:07

标签: sql sql-server left-join

我有三张表PostPostTagMapTagPostTagMap是用于映射具有多个标签的单个帖子的联结表。 我尝试编写查询以将所有帖子都归属于标记名称

发布表

Id    Name

1     Post #1

2     Post #2

标记表

Id   Name

1     JS

2     CSS

PostTagMap表

Id   PostId   TagId

1       1       1
2       1       2

(编辑PostTagMap数据以匹配相关问题)

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(@Tag, T.Name)

@TagNULL时,我只获取帖子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"。

返回所有内容

4 个答案:

答案 0 :(得分:2)

我尝试了所有查询,但一切正常,请尝试此操作

SQLFiddle

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

KeyUp

仅按预期返回帖子1而不是所有内容

编辑:

我理解您的问题现在尝试我的查询

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)

选择所有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,以防WHERE @Tag IS NULL为空,@Tag的其他人希望它可以提供帮助

答案 1 :(得分:2)

你的问题是

WHERE T.Name = ISNULL(@Tag, T.Name)

因为T.Name = T.Name

T.Name IS NULL为FALSE

更改

中的where子句
WHERE (T.Name = @Tag) or (@Tag IS NULL)

同时使用LEFT JOIN或者内部将过滤掉连接表中没有条目的行

答案 2 :(得分:0)

我跑:

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时,它会返回所有内容。 我不知道这是否符合您的期望。

这是我的Fiddle

答案 3 :(得分:0)

因为你对依赖于@Tag条件的行使用LEFT JOIN,所以你基本上不会过滤Post条记录,你总是得到所有这些

如果存在匹配的行,则确实从左连接表中选择其他数据,但这不会影响返回的Post个记录。

你需要做什么:
如果@Tag为空 - 不过滤 否则 - 应用过滤器,并使用内部加入执行:

DECLARE @Tag NVARCHAR(50) = 'Js'   -- or NULL

SELECT P.Id FROM Post P
WHERE @Tag IS NULL
OR EXISTS (
  SELECT 1 FROM PostTagMap M
  JOIN Tag T ON M.TagId = T.Id
  WHERE M.PostId = P.Id
  AND   T.Name = @Tag
)