sql - 尝试仅使用 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 条件是该特殊应用程序中的最佳方式。
提前感谢您的想法。
解决方案
曾几何时,SQL 不支持外连接语法。那是一个古老的世界,电话通过电线连接到墙上,欧洲的每个县都有自己的货币,大多数美国人在电视上观看三四个主要网络之一。
那时,微软甚至没有真正的数据库。WHERE
但是 Sybase 在子句中提供了一个外连接运算符*=
,微软最终将其应用到 SQL Server 中。Microsoft SQL Server 通过 SQL Server 2008 支持这一点。 因此,没有受支持的 SQL Server 版本支持子句中的外连接。WHERE
令人高兴的是,现在存在更好的标准语法(以免我们沮丧并认为事情不会随着时间的推移而变得更好)。子句中的“逗号运算符”FROM
归入其原始定义 - a CROSS JOIN
。CROSS JOIN
过滤掉不匹配的。例如,如果Dtl
没有行,则不CROSS JOIN
返回任何行。
也就是说,没有办法在WHERE
子句中做你想做的事情。有些查询可以复制外部JOIN
,但它们需要对查询进行更多的手术。但是有一个很好的选择,那就是用正确的现代语法编写查询。