如何使 OUTER JOIN 返回零而不是 NULL

use*_*111 -1 join sql-server

我正在尝试在 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
Run Code Online (Sandbox Code Playgroud)

我想在一个 SQL 查询中获取FormIDUserBlogMappingID。如果提供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 
Run Code Online (Sandbox Code Playgroud)

假设: 我们可以假设UserIDWHERE 子句中提供的总是有效的UserID并且存在于User表中。

ype*_*eᵀᴹ 6

您可以使用ISNULL()COALESCE()函数:

SELECT 
    BlogID = B.BlogID, 
    BlogUserMappingID = COALESCE(BUM.BlogUserMappingID, 0)
-- ...
Run Code Online (Sandbox Code Playgroud)

或更详细的CASE表达:

--  BlogUserMappingID = CASE WHEN BUM.BlogUserMappingID IS NULL 
--                          THEN 0 ELSE BUM.BlogUserMappingID 
--                      END
Run Code Online (Sandbox Code Playgroud)

查询需要的第二个更正是将条件 - 关于LEFT连接右侧的表- 从WHEREON(否则左连接成为内部连接):

FROM 
    Blog AS B
        LEFT JOIN BlogUserMapping AS BUM ON  B.BlogID = BUM.BlogID
                                         AND BUM.userID = 444 
WHERE 
    B.BlogID = 23 ;
Run Code Online (Sandbox Code Playgroud)

为了避免具有相同的多行BlogID,您可以使用带有TOP 1, 而不是左连接的内联子查询:

SELECT 
    BlogID = B.BlogID, 
    BlogUserMappingID = COALESCE(
        (SELECT TOP (1) BUM.BlogUserMappingID
         FROM BlogUserMapping AS BUM 
         WHERE B.BlogID = BUM.BlogID
           AND BUM.userID = 444
         ORDER BY BUM.BlogUserMappingID DESC
        ), 0)
FROM 
    Blog AS B
WHERE 
    B.BlogID = 23 ;
Run Code Online (Sandbox Code Playgroud)