The use MySQL ON LEFT JOIN of the table data and WHRERE

background

left join in the process we use mysql query can be described as very common, such as the blog in an article about how many comments, how many goods store in a comment, a comment like how many and so on. However, due to join, on, where keywords such as not familiar with can sometimes cause results not as expected, so today I will summarize together to avoid the pit.

Here I would like to give a scene, and throw two questions, if you can answer it in this article do not read.

Suppose you have a class management application, there is a table classes, saved all classes; there is a table students, saved all students, specific data as follows (Online SQL: https://www.liaoxuefeng.com/wiki/1177760294764384/ 1179611432985088 ):

* The FROM classes the SELECT;
ID name
. 1 class
2 second class
3 three classes
4 four classes

The FROM Students. * The SELECT;
ID class_id Gender name
. 1. 1 Xiaoming M
2. 1 red F.
. 3 Xiao Jun. 1 M
. 4. 1 millet F.
. 5 2 White F.
. 6 soldier 2 M
. 7 2 Kobayashi M
. 8. 3 new small F.
. 9. 3 Wang M
103 Mary F

So now there are two requirements:
1, to find out the name of each class of female students and the corresponding number
2, to find out the total number of students per class

For Requirement 1, most people will be able to come up with the following two sql without hesitation writing, may I ask what is right?

SELECT c.name, count(s.name) as num
FROM classes c left join students s
on s.class_id = c.id
and s.gender = 'F'
group by c.name
或者
SELECT c.name, count(s.name) as num
FROM classes c left join students s
on s.class_id = c.id
where s.gender = 'F'
group by c.name

2 for the needs of the majority of people can come up with the following two sql without thinking of writing, I ask what is right?

SELECT c.name, count (s.name) AS NUM
the FROM classes left the Join Students. S C
ON = c.ID s.class_id
WHERE c.NAME = 'class'
Group by c.NAME
or
SELECT c.name, count ( s.name) AS NUM
the FROM c classes left the Join Students S
ON s.class_id = c.ID
and c.name = 'class'
Group by c.name
please do not continue to turn down! ! To give your own answers, the correct answer is below.
.
.
.
.
.
.
.
.
The answer is two requirements are the first statement is correct, to figure out this problem, you have to understand mysql be deployed for the implementation of the principle of the left join, the following section.

principle

For similar manner mysql nested loops from left join to process, as an example in the following statement:

SELECT * FROM LT LEFT JOIN RT ON P1 (LT, RT)) WHERE P2 (LT, RT)
wherein P1 is a condition on the filter, is considered to be missing TRUE, where P2 is a filter, deletions are also considered TRUE

The execution logic statements may be described as:
the FOR in each Row lt LT {// iterate each row of the left table
BOOL B = FALSE;
the FOR SUCH each Row RT RT in that Pl (lt, RT) {// iterate the right of each table line, satisfying a condition of the join line
IF P2 (lt, rt) { // satisfies filter conditions where
t: = lt || rt; // merge line that outputs
}
B = TRUE; // lt have in RT corresponding row
}
the iF (! B) {// RT been traversed, at RT lt not found a corresponding row, with null fill try line
after // fill null iF P2 (lt, nULL) { filter satisfies where conditions
t: = lt || nULL; // output line lt null and the complement
}
}
}
of course, in actual use buffer MySQL manner optimized to reduce the number of comparisons the line, but this does not affect the execution of critical processes, not within the scope of this article.

From this pseudo-code, we can see two things:
1, with the right table limits ON
if you want to limit the right table, must be carried out on the conditions, where when in the absence of data may result, leading to the left table does not appear in the right table without matching rows of rows in the final result, contrary to our understanding of the left join in. Because the terms of the no right-table match rows of the left table, traverse the right table b = FALSE, NULL filled it will try to use the right table, but at this time we are on the right table rows P2 restrictions, NULL if not satisfied P2 (NULL generally do not satisfy the constraints, unless this iS NULL), then the end result will not be added, resulting in lack of results.
2, the left table WHERE restricting
if not where conditions, regardless of the condition of the left table on how to limit, the left synthesis result table each row will have at least one row of table rows for the left, if the right table if no corresponding line, the right end of the table after traversing b = FALSE, NULL will be used to generate the data line, and this data is redundant. So the left to filter the table must be where.

analysis Summary

Expand following the results of two errors statement needs and the wrong reasons:

Needs a
name NUM
class 2
second class 1
three classes 2
demand since a condition where the right to restrict the table, resulting in missing data (four classes as a result should have 0)

Requirement 2
name NUM
group of 4
second class 0
three classes 0
four classes 0
needs 2 due on the condition of the left table limit, resulting in redundant data (the results of other classes came out that was wrong)

Symptoms and by the above analysis, the conclusion can be drawn:
the left join statement, the left table filter must be placed where conditions, the filter must be put on the table the right conditions

SQL sounds simple, but there are many details of the principles in it, it will cause a little confusion results not as expected, so always pay attention to these details principle, the key to avoiding the wrong time.

Transfer: https://segmentfault.com/a/1190000020458807

Guess you like

Origin www.cnblogs.com/chen-chen-chen/p/11922438.html