sql - 为什么我的左连接不返回空值?

标签 sql tsql sql-server-2008 left-join

在 sql server 2008 中,我有以下查询:

select      
    c.title as categorytitle,
    s.title as subcategorytitle,
    i.title as itemtitle
from categories c
join subcategories s on c.categoryid = s.categoryid
left join itemcategories ic on s.subcategoryid = ic.subcategoryid 
left join items i on ic.itemid = i.itemid and i.siteid = 132
where (ic.isactive = 1 or ic.isactive is null)
order by c.title, s.title

我正在尝试获取其子类别中的项目,但如果类别或子类别中没有项目,我仍然想返回一条记录。永远不会返回没有项目的子类别。我究竟做错了什么?

谢谢

编辑

使用第二个左连接和 where 子句修改查询,但它仍然不返回空值。 :/

编辑 2

将站点 ID 移至项目左连接。当我这样做时,我得到的记录比预期的多。有些项目的站点 ID 为空,我只想在它们具有特定 ID 时将它们包含在内。

编辑 3

表结构:
Categories Table 
-------
CategoryID
Title

SubCategories Table
-------
SubCategoryID
CategoryID
Title

ItemCategories Table
-------
ItemCategoryID
ItemID
SubCategoryID
IsActive

Items Table 
--------
ItemID
Title
SiteID

最佳答案

join items i ... 至 LEFT join items i ...您的查询应该按您的预期工作。

编辑
您不能在 where 子句中过滤 LEFT JOIN 表,除非您考虑空值,因为左连接允许这些列具有值或在没有行匹配时为空:
and i.siteid = 132将丢弃您的任何具有 NULL 的行 i.siteid ,那里不存在。将其移至 ON:
left join items i on ic.itemid = i.itemid and i.siteid = 132
或使 WHERE 处理 NULL:
WHERE ... AND (i.siteid = 132 OR i.siteid IS NULL)
编辑 基于 OP 的编辑 3

SET NOCOUNT ON
DECLARE @Categories table (CategoryID int,Title varchar(30))
INSERT @Categories VALUES (1,'Cat AAA')
INSERT @Categories VALUES (2,'Cat BBB')
INSERT @Categories VALUES (3,'Cat CCC')

DECLARE @SubCategories table (SubCategoryID int,CategoryID int,Title varchar(30))
INSERT @SubCategories VALUES (1,1,'SubCat AAA A')
INSERT @SubCategories VALUES (2,1,'SubCat AAA B')
INSERT @SubCategories VALUES (3,1,'SubCat AAA C')
INSERT @SubCategories VALUES (4,2,'SubCat BBB A')

DECLARE @ItemCategories table (ItemCategoryID int, ItemID int, SubCategoryID int, IsActive char(1))
INSERT @ItemCategories VALUES (1,1,2,'Y')
INSERT @ItemCategories VALUES (2,2,2,'Y')
INSERT @ItemCategories VALUES (3,3,2,'Y')
INSERT @ItemCategories VALUES (4,4,2,'Y')
INSERT @ItemCategories VALUES (5,7,2,'Y')

DECLARE @Items table (ItemID int, Title varchar(30), SiteID int)
INSERT @Items VALUES (1,'Item A',111)
INSERT @Items VALUES (2,'Item B',111)
INSERT @Items VALUES (3,'Item C',132)
INSERT @Items VALUES (4,'Item D',111)
INSERT @Items VALUES (5,'Item E',111)
INSERT @Items VALUES (6,'Item F',132)
INSERT @Items VALUES (7,'Item G',132)
SET NOCOUNT OFF

我不是 100% 确定 OP 是什么,这将返回所有可以在 siteid=132 时加入的信息。如问题中所述
SELECT
    c.title as categorytitle
        ,s.title as subcategorytitle
        ,i.title as itemtitle
        --,i.itemID, ic.SubCategoryID, s.CategoryID
    FROM @Items                          i
        LEFT OUTER JOIN @ItemCategories ic ON i.ItemID=ic.ItemID
        LEFT OUTER JOIN @SubCategories   s ON ic.SubCategoryID=s.SubCategoryID
        LEFT OUTER JOIN @Categories      c ON s.CategoryID=c.CategoryID
    WHERE i.siteid = 132

输出:
categorytitle                  subcategorytitle               itemtitle
------------------------------ ------------------------------ ------------------------------
Cat AAA                        SubCat AAA B                   Item C
NULL                           NULL                           Item F
Cat AAA                        SubCat AAA B                   Item G

(3 row(s) affected)

这将列出所有类别,即使没有匹配到 siteid=132
;WITH AllItems AS
(
SELECT
    s.CategoryID, ic.SubCategoryID, ItemCategoryID, i.ItemID
        ,c.title AS categorytitle, s.title as subcategorytitle, i.title as itemtitle
    FROM @Items                          i
        LEFT OUTER JOIN @ItemCategories ic ON i.ItemID=ic.ItemID
        LEFT OUTER JOIN @SubCategories   s ON ic.SubCategoryID=s.SubCategoryID
        LEFT OUTER JOIN @Categories      c ON s.CategoryID=c.CategoryID
    WHERE i.siteid = 132
)
SELECT
    categorytitle, subcategorytitle,itemtitle
    FROM AllItems
UNION
SELECT
    c.Title, s.Title, null
    FROM @Categories                     c
        LEFT OUTER JOIN @SubCategories   s ON c.CategoryID=s.CategoryID
        LEFT OUTER JOIN @ItemCategories ic ON s.SubCategoryID=ic.SubCategoryID
        LEFT OUTER JOIN AllItems         i ON c.CategoryID=i.CategoryID AND  s.SubCategoryID=i.SubCategoryID
    WHERE i.ItemID IS NULL
ORDER BY categorytitle,subcategorytitle

输出:
categorytitle                  subcategorytitle               itemtitle
------------------------------ ------------------------------ ------------------------------
NULL                           NULL                           Item F
Cat AAA                        SubCat AAA A                   NULL
Cat AAA                        SubCat AAA B                   Item C
Cat AAA                        SubCat AAA B                   Item G
Cat AAA                        SubCat AAA C                   NULL
Cat BBB                        SubCat BBB A                   NULL
Cat CCC                        NULL                           NULL

(7 row(s) affected)

关于sql - 为什么我的左连接不返回空值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2479650/

相关文章:

sql - 使用 qt 连接到 SQL Server

sql - T-SQL 查询 : where column not in is giving wrong result

SQL Server xml字符串解析varchar字段

sql-server-2008 - 将图像插入数据库

sql-server-2008 - Sql Server 'Saving changes is not permitted' 错误 ► 阻止保存需要重新创建表的更改

php - 将数据导出为 .sql 格式。如何逃脱?

sql - 如何根据连接属性的最接近值左连接两个表?

mysql - CakePHP:是否可以强制 find() 运行单个 MySQL 查询

sql - 数据库(最大)字段长度会影响性能吗?

sql-server - 如何检查另一个连接的隔离级别 SQL Server 2008