首页 > 解决方案 > 尝试仅使用 where 条件定义左连接

问题描述

我试图找到一个特定的 SQL 语句来替换旧的 SQL 查询。总而言之,我尝试仅在 where 条件下进行左连接。这是我的测试环境:

create table Mst
(
    Id bigint not null primary key clustered,
    Firstname nvarchar(200) not null,
    Lastname nvarchar(200) not null
);
create table  Dtl
(
    Id bigint not null primary key clustered,
    MstId bigint not null references Mst(Id),
    DetailDescr nvarchar(500) not null
);

我用一些数据填充表格:

declare @i as bigint = 0;
while @i < 999
begin
 insert into Mst values (@i, N'Name ' + Str(@i), N'Lastname ' + Str(@i));
 if (@i % 10 = 0)
    insert into Dtl values (@i*5+0, @i,  N'Description 1 for ' + Str(@i));
 if (@i % 2 = 0)
    insert into Dtl values (@i*5+1, @i,  N'Description 2 for ' + Str(@i));
 if (@i % 3 = 0)
    insert into Dtl values (@i*5+2, @i,  N'Description 3 for ' + Str(@i));
 set @i = @i + 1;
end;

左连接的常用方法是这样的:

select m.Id, m.Firstname, m.Lastname, d.DetailDescr
From Mst m left join Dtl d
on m.id = d.MstId;

此查询返回 1266 行。但是在我尝试迁移的旧应用程序中,选择和源部分仍然是预定义的:

select m.Id, m.Firstname, m.Lastname, d.DetailDescr
From Mst m, Dtl d

旧的 where 条件定义(在单独的软件模块中)不再可用的 LEFT JOIN:

where m.id *= d.MstId

所以我们必须迁移这种方法,并尽可能只修改 where 条件。对于内连接,where 条件很容易定义:

where m.id = d.MstId

但是我需要一个左连接,我发现只修改 where 条件是没有办法的。但是仅重写 where 条件是该特殊应用程序中的最佳方式。

提前感谢您的想法。

标签: sqlsql-serverleft-join

解决方案


曾几何时,SQL 不支持外连接语法。那是一个古老的世界,电话通过电线连接到墙上,欧洲的每个县都有自己的货币,大多数美国人在电视上观看三四个主要网络之一。

那时,微软甚至没有真正的数据库。WHERE但是 Sybase 在子句中提供了一个外连接运算符*=,微软最终将其应用到 SQL Server 中。Microsoft SQL Server 通过 SQL Server 2008 支持这一点。 因此,没有受支持的 SQL Server 版本支持子句中的外连接。WHERE

令人高兴的是,现在存在更好的标准语法(以免我们沮丧并认为事情不会随着时间的推移而变得更好)。子句中的“逗号运算符”FROM归入其原始定义 - a CROSS JOINCROSS JOIN过滤掉不匹配的。例如,如果Dtl没有行,则不CROSS JOIN返回任何行。

也就是说,没有办法在WHERE子句中做你想做的事情。有些查询可以复制外部JOIN,但它们需要对查询进行更多的手术。但是有一个很好的选择,那就是用正确的现代语法编写查询。


推荐阅读