【问题标题】:SQL LEFT JOIN: difference between WHERE and condition inside AND [duplicate]SQL LEFT JOIN:WHERE 和 AND 内部条件之间的区别 [重复]
【发布时间】:2020-04-05 21:52:45
【问题描述】:

有什么区别

select t.*,
a.age
from t
left join a
on t.ID = a.ID and a.column > 10

select t.*,
a.age
from t
left join a
on t.ID = a.ID
where a.column > 10

? 具体来说,当我将条件放在 AND 内与 WHERE 内加入主表的表上时有什么区别?

【问题讨论】:

  • 好问题。创建表,添加一些示例数据并运行查询!
  • 第二个实际上是内部连接
  • 重要的区别在于LEFT JOIN 条件下,您在将两个表连接在一起之前过滤掉不匹配的行,从而只连接到匹配的行
  • 您错过了示例中的FROM :)
  • 这能回答你的问题吗? SQL join: where clause vs. on clause

标签: sql left-join where-clause


【解决方案1】:

那么它们之间有什么区别呢?

举例说明:

CREATE TABLE Students
(
  StudentId INT PRIMARY KEY,
  Name VARCHAR(100)
);
CREATE TABLE Scores
(
  ScoreId INT PRIMARY KEY,
  ExamId INT NOT NULL,
  StudentId INT NOT NULL,
  Score DECIMAL(4,1) NOT NULL DEFAULT 0,
  FOREIGN KEY (StudentId) 
    REFERENCES Students(StudentId)
);
INSERT INTO Students
(StudentId, Name) VALUES
(11,'Joe Shmoe'),
(12,'Jane Doe'),
(47,'Norma Nelson');
INSERT INTO Scores
(ScoreId, ExamId, StudentId, Score) VALUES
(1, 101, 11, 65.2),
(2, 101, 12, 72.6),
(3, 102, 11, 69.6);
--
-- Using an INNER JOIN
--
-- Only Students that have scores
-- So only when there's a match between the 2 tables
--
SELECT stu.Name, sco.Score
FROM Students AS stu
INNER JOIN Scores AS sco
  ON sco.StudentId = stu.StudentId
ORDER BY stu.Name
姓名 |分数 :-------- | :---- 简·多伊 | 72.6 乔什莫 | 65.2 乔什莫 | 69.6
--
-- Using an LEFT JOIN
--
-- All Students, even those without scores
-- Those that couldn't be matched will show NULL's
-- for the fields from the joined table
--
SELECT stu.Name, sco.Score, sco.ScoreId
FROM Students AS stu
LEFT JOIN Scores AS sco
  ON sco.StudentId = stu.StudentId
ORDER BY stu.Name
姓名 |分数 |分数 ID :----------- | :---- | :------ 简·多伊 | 72.6 | 2 乔什莫 | 65.2 | 1 乔什莫 | 69.6 | 3 诺玛纳尔逊 | |
--
-- Using an LEFT JOIN
-- But with an extra criteria in the ON clause
--
-- All Students again.
-- That have scores >= 66
-- But also the unmatched without scores
-- 
SELECT stu.Name, sco.Score, sco.ScoreId
FROM Students AS stu
LEFT JOIN Scores AS sco
  ON sco.StudentId = stu.StudentId

 AND sco.Score >= 66.0

ORDER BY stu.Name
姓名 |分数 |分数 ID :----------- | :---- | :------ 简·多伊 | 72.6 | 2 乔什莫 | 69.6 | 3 诺玛纳尔逊 | |
--
-- Using an LEFT JOIN
-- But with an extra criteria in the WHERE clause
--
-- Only students with scores >= 66
-- The WHERE filters out the unmatched.
-- 
SELECT stu.Name, sco.Score
FROM Students AS stu
LEFT JOIN Scores AS sco
  ON sco.StudentId = stu.StudentId

WHERE sco.Score >= 66.0

ORDER BY stu.Name
姓名 |分数 :-------- | :---- 简·多伊 | 72.6 乔什莫 | 69.6
--
-- Using an INNER JOIN
-- And with an extra criteria in the WHERE clause
--
-- Only Students that have scores >= 66
--
SELECT stu.Name, sco.Score
FROM Students AS stu
INNER JOIN Scores AS sco
  ON sco.StudentId = stu.StudentId
WHERE sco.Score >= 66
ORDER BY stu.Name
姓名 |分数 :-------- | :---- 简·多伊 | 72.6 乔什莫 | 69.6

db小提琴here

您是否注意到 WHERE 子句中的条件如何使 LEFT JOIN 表现得像 INNER JOIN

【讨论】:

    【解决方案2】:

    left join有区别

    left join 行的条件为column > 10 将在那里填充空值

    带有where条件的行会被过滤掉

    inner join没有区别

    示例:

    declare @t table (id int, dummy varchar(20))
    declare @a table (id int, age int, col int)
    
    insert into @t
    select * from (
    values 
        (1, 'pippo'    ),
        (2, 'pluto'    ),
        (3, 'paperino' ),
        (4, 'ciccio'   ),
        (5, 'caio'     ),
        (5, 'sempronio')
    ) x (c1,c2)
    
    insert into @a
    select * from (
    values 
        (1, 38, 2 ),
        (2, 26, 5 ),
        (3, 41, 12),
        (4, 15, 11),
        (5, 39, 7 )
    ) x (c1,c2,c3)
    
    select t.*, a.age
    from @t t
    left join @a a on t.ID = a.ID and a.col > 10
    

    输出:

    id  dummy       age
    1   pippo       NULL
    2   pluto       NULL
    3   paperino    41
    4   ciccio      15
    5   caio        NULL
    5   sempronio   NULL
    

    虽然

    select t.*, a.age
    from @t t
    left join @a a on t.ID = a.ID
    where a.col > 10
    

    输出:

    id  dummy       age
    3   paperino    41
    4   ciccio      15
    

    因此,使用LEFT JOIN,您将始终从第一个表中获得所有行

    如果连接条件为真,您将从连接表中获取填充其值的列,如果条件为假,则它们的列将为NULL

    使用WHERE 条件,您将只获得符合条件的行。

    【讨论】:

    • 你是什么意思“左连接行的条件 > 10 将在那里填充空值”?我仍然无法想象。
    猜你喜欢
    • 2012-09-06
    • 2018-11-10
    • 2011-05-29
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    相关资源
    最近更新 更多