假如现在我们的SQL Server数据库中有三个表:[T_A]、[T_B]和[T_C],它们的建表语句如下:
--建表语句[T_A] CREATE TABLE [dbo].[T_A]( [ID_A] [INT] NOT NULL, CONSTRAINT [PK_T_A] PRIMARY KEY CLUSTERED ( [ID_A] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]; --建表语句[T_B] CREATE TABLE [dbo].[T_B]( [ID_B] [INT] NOT NULL, CONSTRAINT [PK_T_B] PRIMARY KEY CLUSTERED ( [ID_B] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]; --建表语句[T_C] CREATE TABLE [dbo].[T_C]( [ID_C] [INT] NOT NULL, CONSTRAINT [PK_T_C] PRIMARY KEY CLUSTERED ( [ID_C] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY];
[T_A]、[T_B]和[T_C]每个表都只有一个INT类型的列,我们使用下面的语句给这三个表插入数据:
INSERT INTO [dbo].[T_A] VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10); INSERT INTO [dbo].[T_B] VALUES (1),(2),(3),(4),(5); INSERT INTO [dbo].[T_C] VALUES (1),(2),(3);
我们都知道默认情况下,SQL Server中的JOIN语句都是按表出现的顺序执行的,例如下面的SELECT语句中,SQL Server会先执行表[T_A]和[T_B]之间的LEFT JOIN,然后再执行表[T_B]和[T_C]之间的INNER JOIN:
SELECT * FROM [dbo].[T_A] LEFT JOIN [dbo].[T_B] ON [T_A].ID_A=[T_B].ID_B INNER JOIN [dbo].[T_C] ON [T_B].ID_B=[T_C].ID_C
执行结果:
由于上面的SELECT语句中,最后INNER JOIN了表[T_C],所以最后查询结果肯定和表[T_C]的数据行数一致,只有三行。
那么在上面的SELECT语句中,我们能不能在不调整表顺序的情况下,让SQL Server先执行表[T_B]和[T_C]之间的INNER JOIN,再执行表[T_A]和[T_B]之间的LEFT JOIN呢,因为这样的话,由于最后执行的是表[T_A]的LEFT JOIN,所以我们就可以在查询结果中保留表[T_A]的所有数据。
答案是可以的,我们要给表[T_B]和[T_C]之间的INNER JOIN加上小括号:
SELECT * FROM [dbo].[T_A] LEFT JOIN ( [dbo].[T_B] INNER JOIN [dbo].[T_C] ON [T_B].ID_B=[T_C].ID_C ) ON [T_A].ID_A=[T_B].ID_B
执行结果:
由于现在我们给表[T_B]和[T_C]之间的INNER JOIN加上了小括号,所以SQL Server会先执行小括号内的INNER JOIN,再执行小括号外的LEFT JOIN,这样我们就在查询结果中保留了表[T_A]的所有数据。
因此我们可以看到,SQL Server的JOIN是支持通过小括号来改变表与表之间的执行顺序的,通过小括号我们可以让JOIN按照我们想要的顺序来执行。