如何使 OUTER JOIN 返回零而不是 NULL
Posted
技术标签:
【中文标题】如何使 OUTER JOIN 返回零而不是 NULL【英文标题】:How to make an OUTER JOIN return ZERO instead of NULL 【发布时间】:2017-10-28 04:28:26 【问题描述】:我正在尝试在 SQL Server 上完成此操作。最简单的数据表结构如下所示。
Table:Blog
BlogID, Title
----------------
1, FirstBlog
23, Pizza
Table:User
UserID, Name
-------------------
123, james
444, John
Table:UserBlogMapping
UserBlogMappingID, BlogID,UserID
----------------------------------
1, 1, 123
我想在一个 SQL 查询中获取 FormID 和 UserBlogMappingID。如果提供的 UserID 不在映射表中,则返回零,否则返回有效的 userBlogMappingID。我正在尝试运行以下查询,但它不正确。
SELECT
B.BlogID,
BUM.BlogUserMappingID
FROM
Blog AS B
LEFT JOIN BlogUserMapping AS BUM ON B.BlogID = BUM.BlogID
WHERE
(B.BlogID = 23) -- it exists in the table
AND BUM.userID = 444 -- it is NOT in the mmaping table but i want a ZERO return in such case
假设: 我们可以假设 WHERE 子句中提供的 UserID 始终是有效的 UserID 并且存在于 User 表中。
【问题讨论】:
【参考方案1】:您可以将 userID=444 的条件放在 LEFT JOIN 的 ON 子句中。
还有一个 ISNULL 或一个 COALESCE 将 NULL 更改为 0。
使用表变量的示例:
declare @Blog table (BlogID int, Title varchar(30));
insert into @Blog (BlogId, Title) values
(1, 'FirstBlog'),
(23, 'Pizza');
declare @User table (UserID int, Name varchar(30));
insert into @User (UserID, Name) values
(123,'james'),
(444,'John');
declare @BlogUserMapping table (BlogUserMappingID int, BlogID int, UserID int);
insert into @BlogUserMapping (BlogUserMappingID, BlogID, UserID) values
(1, 1, 123),
(2, 23, 123),
(3, 1, 444);
-- Using the criteria in ON clause of the LEFT JOIN
SELECT
B.BlogID,
ISNULL(BUM.BlogUserMappingID,0) as BlogUserMappingID
FROM @Blog B
LEFT JOIN @BlogUserMapping BUM ON (B.BlogID = BUM.BlogID AND BUM.userID = 444)
WHERE B.BlogID = 23;
-- If there are more BlogId=23 with userID=444.
-- But only 1 row needs to be returned then you could also GROUP BY and take the maximum BlogUserMappingID
SELECT
B.BlogID,
MAX(ISNULL(BUM.BlogUserMappingID,0)) as BlogUserMappingID
FROM @Blog B
LEFT JOIN @BlogUserMapping BUM ON (B.BlogID = BUM.BlogID AND BUM.userID = 444)
WHERE B.BlogID = 23
GROUP BY B.BlogID;
-- Using an OR in the WHERE clause would also return a 0.
-- But it would also return nothing if the mapping table has a BlogID=23 with a userID<>444.
-- So not usefull in this case.
SELECT
B.BlogID,
ISNULL(BUM.BlogUserMappingID,0) as BlogUserMappingID
FROM @Blog B
LEFT JOIN @BlogUserMapping BUM ON B.BlogID = BUM.BlogID
WHERE B.BlogID = 23
AND (BUM.userID IS NULL OR BUM.userID = 444);
【讨论】:
您确定我们将在末尾保留“BUM.userID = 444”而不是在 LEFT JOIN 子句中吗? @LukStorms 不,它不会做同样的事情。这不是实现相同结果的替代方法。想想当LEFT JOIN
匹配时会发生什么,但它只匹配BUM.userID <> 444
所在的行。
@hvd 好的,我已经改了。应该在发布之前用映射表中的 23 进行测试。感谢您的建议。
@LukStorms 即使我根据您的建议更正了上述查询,如果“BlogUserMapping”表中有多个记录针对某个“BlogID”(不仅仅是匹配“BUM.UserID”的那个)。对于没有匹配的“BUM.UserID”,它可以正常工作。
@user1451111 好的,添加了一个使用 group by 的额外查询。我以为你想要所有带有特定 BlogID 和 UserID 的 BlogUserMapping。以上是关于如何使 OUTER JOIN 返回零而不是 NULL的主要内容,如果未能解决你的问题,请参考以下文章
getElementsByTagName 返回零而不是 null 为啥
MySQL 数据库中 left outer join 和 left join 啥区别?