暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL的LeftJoin

理论 MYSQL的LEFT JOIN 有时候会变的不一样

如果LFET JOIN B WHERE 条件部分有B的条件,那么它跟主表不再是LEFT

JOIN ,而是变成了 INNER JOIN!

我们创建两个父子表

    mysql> show create table children;
    +----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table |
    +----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | children | CREATE TABLE `children` (
    `ID` bigint unsigned NOT NULL AUTO_INCREMENT,
    `NAME` varchar(45) DEFAULT NULL,
    `SEX` char(1) DEFAULT NULL,
    `AGE` tinyint DEFAULT NULL,
    `FATHER_ID` bigint DEFAULT NULL,
    PRIMARY KEY (`ID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='孩子' |
    +----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.01 sec)


    mysql> show create table FATHER;
    +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table |
    +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | FATHER | CREATE TABLE `FATHER` (
    `ID` bigint unsigned NOT NULL AUTO_INCREMENT,
    `NAME` varchar(45) DEFAULT NULL,
    `MONY` decimal(10,0) DEFAULT NULL,
    PRIMARY KEY (`ID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='父亲' |
    +--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)


    复制

    生成必要的数据

      mysql> select * from FATHER;
      +----+--------+------+
      | ID | NAME | MONY |
      +----+--------+------+
      | 1 | 王五 | 3000 |
      | 2 | 张三 | 3500 |
      | 3 | 李四 | 5000 |
      | 4 | 刘二 | 8000 |
      | 5 | 陈七 | 5500 |
      | 6 | 杨八 | 7500 |
      +----+--------+------+
      6 rows in set (0.00 sec)
      复制


        mysql> select * from children;
        +----+-----------+------+------+-----------+
        | ID | NAME | SEX | AGE | FATHER_ID |
        +----+-----------+------+------+-----------+
        | 1 | 王八 | 男 | 38 | 1 |
        | 2 | 王高 | 男 | 28 | 1 |
        | 3 | 王艳 | 女 | 18 | 1 |
        | 4 | 张雪 | 女 | 33 | 2 |
        | 5 | 张亮 | 男 | 25 | 2 |
        | 6 | 李贵 | 男 | 27 | 3 |
        | 7 | 李丽 | 女 | 25 | 3 |
        | 8 | 杨莉 | 女 | 23 | 6 |
        | 9 | 杨雪 | 女 | 22 | 6 |
        | 10 | 杨七郎 | 男 | 35 | 6 |
        +----+-----------+------+------+-----------+
        10 rows in set (0.00 sec)
        复制


        实验一   没有条件的时候

          mysql> SELECT A.NAME,A.MONY,B.NAME,B.AGE,B.SEX
          -> FROM books.FATHER A
          -> LEFT JOIN books.children B ON A.ID=B.FATHER_ID
          -> ORDER BY A.ID ASC;
          +--------+------+-----------+------+------+
          | NAME | MONY | NAME | AGE | SEX |
          +--------+------+-----------+------+------+
          | 王五 | 3000 | 王艳 | 18 | 女 |
          | 王五 | 3000 | 王高 | 28 | 男 |
          | 王五 | 3000 | 王八 | 38 | 男 |
          | 张三 | 3500 | 张亮 | 25 | 男 |
          | 张三 | 3500 | 张雪 | 33 | 女 |
          | 李四 | 5000 | 李丽 | 25 | 女 |
          | 李四 | 5000 | 李贵 | 27 | 男 |
          | 刘二 | 8000 | NULL | NULL | NULL |
          | 陈七 | 5500 | NULL | NULL | NULL |
          | 杨八 | 7500 | 杨七郎 | 35 | 男 |
          | 杨八 | 7500 | 杨雪 | 22 | 女 |
          | 杨八 | 7500 | 杨莉 | 23 | 女 |
          +--------+------+-----------+------+------+
          12 rows in set (0.00 sec)
          复制

          认为非常正常,没有孩子的要展现出来的!

          执行计划也很正常

            +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
            | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
            +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
            |  1 | SIMPLE      | A     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |   100.00 | Using temporary; Using filesort            |
            | 1 | SIMPLE | B | NULL | ALL | NULL | NULL | NULL | NULL | 10 | 100.00 | Using where; Using join buffer (hash join) |
            +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
            复制


            实验二 带条件的



              mysql> SELECT A.NAME,A.MONY,B.NAME,B.AGE,B.SEX
              -> FROM books.FATHER A
              -> LEFT JOIN books.children B ON A.ID=B.FATHER_ID
              -> WHERE B.SEX='男'
              -> ORDER BY A.ID ASC;
              +--------+------+-----------+------+------+
              | NAME | MONY | NAME | AGE | SEX |
              +--------+------+-----------+------+------+
              | 王五 | 3000 | 王八 | 38 | 男 |
              | 王五 | 3000 | 王高 | 28 | 男 |
              | 张三 | 3500 | 张亮 | 25 | 男 |
              | 李四 | 5000 | 李贵 | 27 | 男 |
              | 杨八 | 7500 | 杨七郎 | 35 | 男 |
              +--------+------+-----------+------+------+
              复制

              主表的被屏蔽掉了,而执行计划是B表为主表,驱动表

                +----+-------------+-------+------------+--------+---------------+---------+---------+-------------------+------+----------+----------------------------------------------+
                | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
                +----+-------------+-------+------------+--------+---------------+---------+---------+-------------------+------+----------+----------------------------------------------+
                | 1 | SIMPLE | B | NULL | ALL | NULL | NULL | NULL | NULL | 10 | 10.00 | Using where; Using temporary; Using filesort |
                | 1 | SIMPLE | A | NULL | eq_ref | PRIMARY | PRIMARY | 8 | books.B.FATHER_ID | 1 | 100.00 | Using where |
                +----+-------------+-------+------------+--------+---------------+---------+---------+-------------------+------+----------+----------------------------------------------+
                复制


                查看SQL改写

                  mysql> show warnings
                  -> ;
                  +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
                  | Level | Code | Message |
                  +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
                  | Note | 1003 | /* select#1 */ select `books`.`A`.`NAME` AS `NAME`,`books`.`A`.`MONY` AS `MONY`,`books`.`B`.`NAME` AS `NAME`,`books`.`B`.`AGE` AS `AGE`,`books`.`B`.`SEX` AS `SEX` from `books`.`FATHER` `A` join `books`.`children` `B` where ((`books`.`B`.`SEX` = '男') and (`books`.`A`.`ID` = `books`.`B`.`FATHER_ID`)) order by `books`.`A`.`ID` |
                  +-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
                  1 row in set (0.00 sec)


                  复制

                  被改写成了  JOIN 

                    select
                    `books`.`A`.`NAME` AS `NAME`,
                    `books`.`A`.`MONY` AS `MONY`,
                    `books`.`B`.`NAME` AS `NAME`,
                    `books`.`B`.`AGE` AS `AGE`,
                    `books`.`B`.`SEX` AS `SEX`
                    from
                    `books`.`FATHER` `A`
                    join `books`.`children` `B`
                    where
                    (
                    (`books`.`B`.`SEX` = '男')
                    and (`books`.`A`.`ID` = `books`.`B`.`FATHER_ID`)
                    )
                    order by
                    `books`.`A`.`ID`
                    复制


                    如果不是你希望的,还是希望要回LEFT JOIN 该这样写 把条件写在ON 后面

                      mysql> SELECT A.NAME,A.MONY,B.NAME,B.AGE,B.SEX
                      -> FROM books.FATHER A
                      -> LEFT JOIN books.children B ON A.ID=B.FATHER_ID AND B.SEX='男'
                      -> ORDER BY A.ID ASC;
                      +--------+------+-----------+------+------+
                      | NAME | MONY | NAME | AGE | SEX |
                      +--------+------+-----------+------+------+
                      | 王五 | 3000 | 王高 | 28 | 男 |
                      | 王五 | 3000 | 王八 | 38 | 男 |
                      | 张三 | 3500 | 张亮 | 25 | 男 |
                      | 李四 | 5000 | 李贵 | 27 | 男 |
                      | 刘二 | 8000 | NULL | NULL | NULL |
                      | 陈七 | 5500 | NULL | NULL | NULL |
                      | 杨八 | 7500 | 杨七郎 | 35 | 男 |
                      +--------+------+-----------+------+------+
                      7 rows in set (0.00 sec)
                      复制
                        +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
                        | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
                        +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
                        | 1 | SIMPLE | A | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 100.00 | Using temporary; Using filesort |
                        | 1 | SIMPLE | B | NULL | ALL | NULL | NULL | NULL | NULL | 10 | 100.00 | Using where; Using join buffer (hash join) |
                        +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
                        复制


                          select
                          `books`.`A`.`NAME` AS `NAME`,
                          `books`.`A`.`MONY` AS `MONY`,
                          `books`.`B`.`NAME` AS `NAME`,
                          `books`.`B`.`AGE` AS `AGE`,
                          `books`.`B`.`SEX` AS `SEX`
                          from
                          `books`.`FATHER` `A`
                          left join `books`.`children` `B` on(
                          (
                          (`books`.`B`.`SEX` = '男')
                          and (`books`.`A`.`ID` = `books`.`B`.`FATHER_ID`)
                          )
                          )
                          where
                          true
                          order by
                          `books`.`A`.`ID`
                          复制



                          MYSQL开发

                          MYSQL 常用函数

                          MYSQL 批量生成触发器

                          如何优雅更新MYSQL大表?


                          文章转载自海鲨数据库架构师,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                          评论