mysql - MySQL 中的 LEFT JOIN 给出与 INNER 或 RIGHT JOIN 相同的结果

标签 mysql join

在下面的查询中,我加入了一个包含 45324 个项目的样本表。结果只给我 39426,其中没有一个包含空 SUM、SUM_YIELD 或其他任何内容...谁能解释为什么 LEFT、RIGHT 和 INNER JOIN 给我相同的结果?

SELECT
  `gs_prod`.`samples`.`id` AS `id`,
  `gs_prod`.`samples`.`customer_name` AS `customer_name`,
  `qcs_demux_stats_view`.`sample_name` AS `sample_name`,
  FORMAT(
    SUM(`qcs_demux_stats_view`.`clusters`),
    0
  ) AS `SUM`,
  FORMAT(
    SUM(`qcs_demux_stats_view`.`yield`),
    0
  ) AS `SUM_YIELD`,
  ROUND(
    (
      SUM(
        (
          `qcs_demux_stats_view`.`perc_q30` * `qcs_demux_stats_view`.`clusters`
        )
      ) / SUM(`qcs_demux_stats_view`.`clusters`)
    ),
    2
  ) AS `perc_q30`
FROM
  (
    `gs_prod`.`qcs_demux_stats_view`
  JOIN
    `gs_prod`.`samples` ON(
      (
        `gs_prod`.`samples`.`id` = `qcs_demux_stats_view`.`sample_id`
      )
    )
  )
WHERE
  (
    `qcs_demux_stats_view`.`parent_id` IN(
    SELECT
      `gs_prod`.`qcs`.`id`
    FROM
      `gs_prod`.`qcs`
    WHERE
      (
        (`gs_prod`.`qcs`.`status` = 1) AND(
          `gs_prod`.`qcs`.`deleted` = 0
        )
      )
  ) AND(
    `qcs_demux_stats_view`.`status` = 1
  )
  )
GROUP BY
  `gs_prod`.`samples`.`id`,
  `qcs_demux_stats_view`.`sample_name`,
  `gs_prod`.`samples`.`customer_name`

所以我得到这样的结果:

id customer_name sample_name SUM SUM_YIELD perc_q30
41453 103312-001-005-BC105 103312-001-005-BC105 7 0 88.27 
41485 103312-001-005-BC137 103312-001-005-BC137 285 0 93.31
41517 103312-001-005-BC169 103312-001-005-BC169 270 0 91.46

但也希望有类似的行(没有来自 qcs_demux_stats 的数据):

41517 103312-001-005-BC169 103312-001-005-BC169 0 0 NaN

左边三列来自samples表,第一列是ON子句中匹配的id,右边三列是qcs_demux_stats表的分组数据。

最佳答案

WHERE 子句中的条件要求 qcs_demux_stats_view 中的列为非 NULL,这将导致 OUTER 联接等同于 INNER 联接。

思考 OUTER join 做什么、它如何运作的一种方法...

当没有找到匹配的行时,查询会生成一个由所有 NULL 值组成的虚拟行。此虚拟“匹配”行允许返回该行。

如果我们要求虚拟行中的一列为非 NULL,则该行将被排除。这基本上会丢弃所有生成的虚拟行。呈现等同于内部联接的结果。

要获得外连接结果,可以:

更改 WHERE 子句中的条件以允许返回 NULL 值

将这些条件重新定位到 OUTER 连接的 ON 子句


我建议将驱动表放在左侧,并将查询编写为 LEFT 外连接。 (最好将 RIGHT 外连接留作学术练习。)

 SELECT s.`id`                           AS `id`
      , s.`customer_name`                AS `customer_name`
      , v.`sample_name`                  AS `sample_name`
      , FORMAT(  SUM(v.`clusters`) ,0)   AS `SUM`
      , FORMAT(  SUM(v.`yield`)    ,0)   AS `SUM_YIELD`

      , ROUND(   SUM( v.`perc_q30` * v.`clusters` )
               / SUM( v.`clusters` )
        ,2
        )                               AS `perc_q30`

   FROM `gs_prod`.`samples` s

   LEFT
   JOIN `gs_prod`.`qcs_demux_stats_view` v
     ON v.`sample_id` = s.`id`
    AND v.`parent_id` IN ( SELECT q.`id`
                             FROM `gs_prod`.`qcs` q
                            WHERE q.`status` = 1
                              AND q.`deleted` = 0
                         )
    AND v.`status` = 1

  GROUP
     BY s.`id`
      , v.`sample_name`
      , s.`customer_name`

这实际上是说,从 samples 中获取所有行,以及从 qcs_demux_stats_view 中获取所有匹配行。

如果在 qcs_demux_stats_view 中找到匹配行,则从 samples(左侧的驱动表)返回该行。对于这些行,列的值来自 qcs_demux_stats_view 将为 NULL。

关于mysql - MySQL 中的 LEFT JOIN 给出与 INNER 或 RIGHT JOIN 相同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49493621/

相关文章:

mysql - 如何匹配连接表和相关表中的列名和值?

mysql - SQL-如何将两个表与具有不同条件的两个表计数组合起来

Mysql - 触发器不更新我的数据库

php - 如何估计网站上可能的最大用户数?

mysql - Linux - 将 SQL 文件导入到不存在的数据库中

mysql - 如何使用特定的相关值更新受尊重的字段值

从多个表返回所有列的函数 (PostgreSQL)

php - MySql 半动态表名

C# 数组作为 MySQL Select 语句的一部分?

mysql - sql选择对同一个表的多个引用