【问题标题】:Why MySQL LEFT JOIN produces NULL results?为什么 MySQL LEFT JOIN 会产生 NULL 结果?
【发布时间】:2021-04-22 02:21:09
【问题描述】:

我一直在研究费用跟踪系统。我有三个主要表格:'expenses'、'expense_reports'、'payments'。

我的数据库结构是这样的:

  • “费用”属于一个“费用报告”
  • “expense_reports”有很多“费用”
  • “expense_reports”属于许多“付款”
  • “付款”属于许多“费用报告”

我为“expense_reports”和“payments”表添加了一个数据透视表,即“expense_report_payment”,以处理多对多关系。 'expense_report_payment' 表有 ff 字段:

  • 身份证
  • expense_report_id
  • payment_id
  • 付款

这是我获取费用和付款总额的查询:

SELECT SUM(ex.`amount`) AS total_expenses, SUM(erp.`payment`) AS total_payment FROM `expenses` ex
JOIN `expense_reports` er ON er.`id` = ex.`expense_report_id`
LEFT JOIN `expense_report_payment` erp ON erp.`expense_report_id` = er.`id`
LEFT JOIN `payments` p ON p.`id` = erp.`payment_id`
WHERE ex.`deleted_at` IS NULL
AND er.`deleted_at` IS NULL
AND er.`rejected_at` IS NULL
AND er.`cancelled_at` IS NULL
AND p.`deleted_at` IS NULL
AND p.`cancelled_at` IS NULL
AND p.`received_at` IS NOT NULL

即使还没有付款,我也使用 LEFT JOIN 来显示费用结果。但是,我得到了 NULL 结果。

【问题讨论】:

  • 好吧....AND p.received_at IS NOT NULL 使得LEFT JOINpayments 实际上是INNER JOIN,因为这个条件实际上是一个需要一个付款人
  • 天哪。它确实提供了我想要的。但如果有付款,我需要它。只有在收到完成交易的情况下才能考虑付款。

标签: mysql sql mariadb


【解决方案1】:

您要求 p.received_at 不为 NULL,因此必须始终有付款。

我质疑您为什么要加入付款;您没有使用该表中的任何内容,尽管您正在限制您向 erps 报告的内容,所有这些字段都为空。

我猜你只想加入已经收到的付款:

LEFT JOIN payments p ON p.id=erp.payment_id AND p.received_at IS NOT NULL

或者如果您想在没有付款或已收到付款时包含,但在未收到付款时排除,请保持联接不变并将 where 条件更改为:

AND (p.id IS NULL or p.`received_at` IS NOT NULL)

您可能希望某些 p.foo IS NULL 条件也出现在 join ON 子句中。

【讨论】:

  • 谢谢,如果还没有付款,它不会再返回空值。但是,如果有付款,即使尚未收到,仍会显示总付款金额。
【解决方案2】:

感谢大家的帮助。我设法通过在 LEFT JOIN 中加入 'expense_report_payment' 和 'payments' 表来解决这个问题。

SELECT 
  IFNULL(SUM(ex.`amount`), 0) AS total_expenses,
  IFNULL(SUM(erp.payment), 0) AS total_payment
FROM
  `expenses` ex 
  JOIN `expense_reports` er 
    ON er.`id` = ex.`expense_report_id` 
    AND er.`deleted_at` IS NULL 
    AND er.`rejected_at` IS NULL 
    AND er.`cancelled_at` IS NULL 
  LEFT JOIN 
    (SELECT 
      ep.*
    FROM
      `expense_report_payment` ep 
      JOIN `payments` p 
        ON p.`id` = ep.`payment_id`
    WHERE p.`received_at` IS NOT NULL
    AND p.`deleted_at` IS NULL
    AND p.`cancelled_at` IS NULL
    ) AS erp 
    ON erp.expense_report_id = er.`id` 
WHERE ex.`deleted_at` IS NULL 

【讨论】:

    猜你喜欢
    • 2017-03-19
    • 2017-02-21
    • 2019-03-25
    • 1970-01-01
    • 2018-02-28
    • 2012-02-17
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多