具有多个IF语句的MySQL查询未返回预期结果

时间:2016-09-19 16:49:59

标签: mysql if-statement

我有一个带有四个IF语句的MySQL查询,应该根据里面的条件将别名设置为“1”或“0”。虽然我没有任何错误,但唯一返回正确值的IF是具有is_paid别名的IF。

我仔细检查了其他三个别名的条件,即使它们没问题,我仍然会得到虚假的结果。

我做错了吗?有什么办法可以编写查询,这样我就能得到预期的结果吗?

以下是查询:

SELECT r.doc_number,
       r.doc_date,
       r.due_date,
       r.currency,
       r.amount,
       r.vat,
       r.vatammount,
       (r.amount + r.vatammount) final_amount,
       r.currency,
       b.boq_id,
       b.boq_comp_id,
       b.boq_client_id,
       b.boq_agency,
       b.boq_date,
       b.boq_orders,
       b.receivable_id,
       c.comp_name,
       crm.`cn-name-first`,
       crm.`cn-name-last`,
       bi.inv_path,
       (SELECT SUM(amount_recieved) FROM receivables_payments WHERE r_id = b.receivable_id) total_amount_received,
       IF (r.amount + r.vatammount = (SELECT SUM(amount_recieved) FROM receivables_payments WHERE r_id = b.receivable_id), '1', '0') AS is_paid,
       IF (CURRENT_DATE >= r.due_date AND r.amount + r.vatammount != (SELECT SUM(amount_recieved) FROM receivables_payments WHERE r_id = b.receivable_id), '1', '0') AS is_overdue,
       IF (r.due_date < CURRENT_DATE AND r.amount + r.vatammount != (SELECT SUM(amount_recieved) FROM receivables_payments WHERE r_id = b.receivable_id), '1', '0') AS is_outstanding,
       IF (r.due_date = CURRENT_DATE AND r.amount + r.vatammount != (SELECT SUM(amount_recieved) FROM receivables_payments WHERE r_id = b.receivable_id), '1', '0') AS is_due_today
FROM receivables r
LEFT JOIN boq b ON b.receivable_id = r.id
LEFT JOIN boq_invoices bi ON bi.inv_boq_id = b.boq_id
LEFT JOIN comp_companies c ON c.comp_id = b.boq_comp_id
LEFT JOIN crm_contacts crm ON crm.contact_id = b.boq_client_id
WHERE r.status = 'active'
  AND r.doc_type = 'inv'
  AND b.boq_status = 'active'
GROUP BY r.id
HAVING is_due_today = '1'
ORDER BY r.doc_date DESC
LIMIT 10

2 个答案:

答案 0 :(得分:0)

您遇到null - 比较问题。 20 != 0true,但20 != nullnull(效果与false中的IF相同。)

IF (... r.amount + r.vatammount != 
      (SELECT SUM(amount_recieved) 
       FROM receivables_payments WHERE r_id = b.receivable_id)
   , '1', '0') AS is_overdue,
如果null/false中没有任何符合行的情况,

将为receivables_payments(因此可能在没有任何付款的情况下),因为SUM(amount_recieved)将是null 。所以你不会得到正确的旗帜。

当值为coalesce(value,0)时,您可以使用0获取null,以便您可以按照以下方式进行比较:

IF (... r.amount + r.vatammount != 
      COALESCE(SELECT SUM(amount_recieved) 
       FROM receivables_payments WHERE r_id = b.receivable_id),0)
   , '1', '0') AS is_overdue,

实际上,对于使用总和的所有5列(标志和total_amount_received),您应该执行此操作,例如,如果您的帐单金额为0,则标记is_paid也不正确。

答案 1 :(得分:0)

您的查询存在一般问题:

  • 首先,每个应收款可以有很多boq。您按应收款进行分组,但未指定要显示的boq数据(例如,属于具有max(b.boq_id)的应收款的所有Boq的最大boq_id)。所以你只需要显示一个匹配的boq_id,一个匹配的boq_comp_id等,都是任意选择的。它们甚至不必属于同一条记录,因此您可以从一条记录中获取boq_id,从另一条记录中获取boq_comp_id等。
  • 然后你加入boq。因此,即使他们没有任何关联的boq,您也希望显示应收账款。但是在WHERE子句中,您需要b.boq_status = 'active'。外连接记录的列为NULL。因此,没有外部联接记录匹配,因此您立即解雇它们。你想要到外连接,然后把条件放在ON子句中,或者你没有,然后使用INNER JOIN(或简短的JOIN)。

现在进行评估:

  • is_overdue是指付款金额与支付金额不匹配,due_date是今天或过去。
  • is_outstanding是指付款金额与付款金额不符,且due_date已过去。
  • is_due_today是支付金额与支付金额不符,而且今天是due_date。

对我来说没问题。好吧,你将超额付款视为未支付,但也许你的数据库中不可能。如果未达到金额且今天为due_date,则设置is_overdue和is_due_today。如果未达到金额并且due_date是上周,则设置is_overdue和is_outstanding。

不是这样的吗?你和他们的实际问题是什么?

相关问题