Home > Archives > sql示例

sql示例

Publish:

前期准备

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
CREATE DATABASE `db2021` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;

-- db2021.student_club definition

CREATE TABLE `student_club` (
  `student_id` varchar(100) NOT NULL,
  `club_id` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- db2021.student_info definition

CREATE TABLE `student_info` (
  `student_id` varchar(100) NOT NULL,
  `gender` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`student_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO db2021.student_club (student_id,club_id) VALUES
	 ('1001','A01'),
	 ('1003','A01'),
	 ('1004','A02'),
	 ('1005','A02');
	 
INSERT INTO db2021.student_info (student_id,gender) VALUES
	 ('1001','male'),
	 ('1002','male'),
	 ('1003','female');

写法一

1
2
3
4
5
6
7
8
9
10
11
12
SELECT 
	sc.*, si.gender 
FROM student_club sc 
	left join 
		student_info si on sc.student_id = si.student_id ;

student_id|club_id|gender|
----------+-------+------+
1001      |A01    |male  |
1003      |A01    |female|
1004      |A02    |      |
1005      |A02    |      |

执行顺序

首先从student_club取出所有数据,然后根据on后面的条件从student_info取出符合条件的数据。

写法二

1
2
3
4
5
6
7
8
9
10
11
12
SELECT 
	sc.*, si.gender 
FROM student_club sc 
	left join 
		student_info si on sc.student_id = si.student_id and si.gender = 'female';
	
student_id|club_id|gender|
----------+-------+------+
1001      |A01    |      |
1003      |A01    |female|
1004      |A02    |      |
1005      |A02    |      |

其实 1001 的gender是有值的,但是因为条件过滤,它没有值了。

写法三

1
2
3
4
5
6
7
8
9
10
SELECT 
	sc.*, si.gender 
FROM student_club sc 
	left join 
		student_info si on sc.student_id = si.student_id 
WHERE si.gender = 'female';
	
student_id|club_id|gender|
----------+-------+------+
1003      |A01    |female|

首先从student_club取出数据,然后根据on后面的条件从student_info取出数据,根据where后面的条件对数据进行过滤。

写法四

1
2
3
4
5
6
7
8
9
10
SELECT 
	sc.*, si.gender 
FROM student_club sc 
	join 
		student_info si on sc.student_id = si.student_id ;
	
student_id|club_id|gender|
----------+-------+------+
1001      |A01    |male  |
1003      |A01    |female|

写法五

1
2
3
4
5
6
7
8
9
SELECT 
	sc.*, si.gender 
FROM student_club sc 
	join 
		student_info si on sc.student_id = si.student_id and si.gender = 'female';
	
student_id|club_id|gender|
----------+-------+------+
1003      |A01    |female|

写法六

1
2
3
4
5
6
7
8
9
10
SELECT 
	sc.*, si.gender 
FROM student_club sc 
	join 
		student_info si on sc.student_id = si.student_id 
WHERE si.gender = 'female';

student_id|club_id|gender|
----------+-------+------+
1003      |A01    |female|

表面上看出来的结果和 写法五 是一样的,

在连接表时,ONWHERE 的使用场景以及性能上的区别如下:

使用场景:

ON:在SQL查询中,当使用JOIN(如INNER JOINLEFT JOINRIGHT JOINFULL JOIN等)来连接两个或多个表时,ON子句用于指定连接条件。它告诉数据库如何根据这些条件将表连接在一起。这些条件通常涉及两个表中的列之间的比较。

WHERE:WHERE子句在连接表后用于过滤结果集。它可以包含任何有效的SQL条件,以限制返回的行。虽然WHERE子句也可以包含连接条件,但在大多数情况下,使用ON子句来指定连接条件会使查询更清晰和易于理解。

性能区别:

从性能的角度来看,ON和WHERE在连接表时的差异主要取决于查询优化器和执行计划。然而,一般来说,当连接条件在ON子句中指定时,数据库可能会更有效地优化查询,因为它可以在生成连接结果之前应用这些条件。

另一方面,当连接条件在WHERE子句中指定时,数据库首先会生成完整的连接结果集,然后再应用过滤条件。这可能会导致更大的中间结果集和更高的内存使用,特别是对于大型表或复杂的连接操作。

此外,当使用LEFT JOIN或RIGHT JOIN时,ON和WHERE的行为会有所不同。在LEFT JOIN中,ON子句指定的条件用于确定哪些行从右表(或“被连接”的表)包括在结果集中,而WHERE子句用于过滤结果集。如果在WHERE子句中指定了与右表相关的条件,它可能会排除那些在LEFT JOIN中应该出现的行。

总结:

使用ON子句来指定连接条件可以使查询更清晰、更易于理解,并且可能有助于数据库更有效地优化查询。

WHERE子句应该用于在连接表后过滤结果集,而不是指定连接条件(除非在隐式连接中使用)。

当使用LEFT JOIN或RIGHT JOIN时,请注意ON和WHERE在行为上的差异,以避免意外的结果。

声明: 本文采用 BY-NC-SA 授权。转载请注明转自: Ding Bao Guo