【问题标题】:mySQL how to left joinmySQL如何左连接
【发布时间】:2020-01-22 12:57:34
【问题描述】:

我正在尝试从我的 SQL 数据库中获取一些数据,但我遇到了一些我不明白的问题。 这是我的查询:

SELECT SUM(t0_.in_budget_hours) AS sclr_0, 
SUM(t0_.billable_amount) AS sclr_1, 
SUM(t0_.out_budget_hours) AS sclr_2, 
SUM(t0_.unprod_hours) AS sclr_3, 
SUM(t0_.off_hours) AS sclr_4,
SUM(t0_.duration) AS sclr_5, 
SUM(t0_.in_budget_hours) / SUM(t0_.duration) * 100 AS sclr_6, 
CONCAT(c1_.name, ' ', c1_.lastname) AS sclr_7, 
c1_.alias AS alias_8, 
c1_.email AS email_9 
FROM collaborator c1_
RIGHT JOIN timesheet t0_ ON (c1_.email = t0_.email) 
WHERE t0_.entry_date BETWEEN '2020-01-01 00:00:00' AND '2020-01-22 23:59:59' 
GROUP BY sclr_7, c1_.alias, c1_.email 
ORDER BY sclr_7 ASC

我有很多从时间表表中计算出来的信息,我想将这些计算结果与合作者姓名合并。

我希望拥有所有协作者并通过时间表加入他们,即使他们没有任何时间表(LEFT JOIN)。如果没有与协作者相关的行,则总和结果应为 0,但协作者应出现在结果数据集中。但目前如果协作者没有任何时间表BETWEEN '2020-01-01 00:00:00' AND '2020-01-22 23:59:59',他将不会出现在结果中。

我使用此线程What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN? 尝试了几种类型的连接,但对我没有任何效果。 有人可以告诉我即使没有时间表如何让所有合作者参与进来吗?

【问题讨论】:

  • WHERE (a0_.entry_date BETWEEN '2020-01-01 00:00:00' AND '2020-01-22 23:59:59') OR (a0_.entry_date IS NULL) 可以工作
  • 您的a0_ 表是什么?它似乎没有在你的 sn-p 中声明
  • WHERE (a0_.entry_date BETWEEN '2020-01-01 00:00:00' AND '2020-01-22 23:59:59') OR (a0_.entry_date IS NULL) 不起作用,但对这个提议很有效。 a0_ t0_,抱歉我已经修复了这个错误。
  • 您通常 GROUP BY 与您 SELECT 相同的列,除了那些是设置函数的参数的列。
  • 我对 group by 没有任何问题,所以这与我的加入问题有关吗?

标签: mysql sql left-join


【解决方案1】:

我希望拥有所有协作者并通过时间表加入他们,即使他们没有任何时间表(LEFT JOIN)。

您的RIGHT JOIN 似乎与此相反。事实上,它将占用entry_date 中的所有行,即使是collaborator 中没有匹配记录的行。 RIGHT JOINs 对于习惯从左到右阅读的人来说是相当违反直觉的。

我会将您的JOIN 改写为以下LEFT JOIN

FROM collaborator c1_
LEFT JOIN timesheet t0_ 
    ON c1_.email = t0_.email
    AND t0_.entry_date >= '2020-01-01'
    AND t0_.entry_date < '2020-01-23' 

旁注:

  • timesheet 上的条件需要从WHERE 子句移至JOINON 部分

  • 我重写了日期过滤器以使用半开间隔,我发现它更便于阅读和理解

【讨论】:

  • 谢谢,但这不起作用。我在右加入之前尝试了左加入。我还尝试更改源表(来自时间表的合作者 )但没有工作。
  • @Shining:请注意,我还将条件从WHERE 子句移至LEFT JOINON 部分,您是否已经尝试过?请根据您的真实数据尝试一下。
  • 在我最初的 sql 请求中,我和你有相同的子句ON。我不太了解您所做的更改,对我而言,您仅将 RIGHT JOIN 更改为 LEFT JOIN,但没有其他任何更改。 ( between 子句与您的日期过滤器相同)
  • @Shining:仔细看。 entry_date 上的过滤器位于 WHERE 子句 (WHERE t0_.entry_date BETWEEN '2020-01-01 00:00:00' AND '2020-01-22 23:59:59') 中。我对其进行了更改,使其位于LEFT JOINON 子句中。所以基本上我的查询根本没有WHERE 子句。
  • 你是最棒的!这是我的错误!谢谢你。您是否有一些文件可以更准确地解释我的错误?我的意思是连接中的子句 ON 和 WHERE 之间的区别?再次感谢你!
【解决方案2】:

您需要一个OUTER 连接来连接两个表,其中可能两个表之一中没有任何匹配的行。

默认连接是INNER,这意味着只返回匹配的行。

在我看来,LEFT OUTER 应该可以满足您的需求。

select * from a LEFT OUTER JOIN b 表示来自a所有 行,以及来自b 的匹配行(或NULLs)

More details here

【讨论】:

  • SELECT SUM(t0_.in_budget_hours) AS sclr_0, SUM(t0_.billable_amount) AS sclr_1, SUM(t0_.out_budget_hours) AS sclr_2, SUM(t0_.unprod_hours) AS sclr_3, SUM(t0_.off_hours) AS sclr_4, SUM(t0_.duration) AS sclr_5, SUM(t0_.in_budget_hours) / SUM(t0_.duration) * 100 AS sclr_6, CONCAT(c1_.name, ' ', c1_.lastname) AS sclr_7, c1_.alias AS alias_8, c1_.email AS email_9 FROM collaborator c1_ LEFT OUTER JOIN timesheet t0_ ON (c1_.email = t0_.email) WHERE t0_.entry_date BETWEEN '2020-01-01 00:00:00' AND '2020-01-22 23:59:59' GROUP BY sclr_7, c1_.alias, c1_.email ORDER BY sclr_7 ASC 不工作
  • 如果我没记错的话,LEFT JOIN 和 mysql 的 LEFT OUTER JOIN 是一样的
  • 我很确定 MySQL(和大多数 RDBMS)上的默认 JOININNER。我无法在 MySQL 文档中轻松找到对它的引用,但它是 stated clearly herehere
猜你喜欢
  • 1970-01-01
  • 2012-11-13
  • 2012-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-07
相关资源
最近更新 更多