【问题标题】:MySQL SELECT IFNULL then compare it numerically with other columnMySQL SELECT IFNULL 然后将其与其他列进行数字比较
【发布时间】:2020-06-01 07:00:55
【问题描述】:

我尝试了多种方法在选择时将 NULL 转换为数字 0:

SELECT
  ss.id AS staff_id,
  u.realname AS realname,
  ss.amount AS salary_amount,
  IF(s.paid_amount IS NOT NULL, s.paid_amount,0.00) AS paid_amount,
  (ss.amount-s.paid_amount)
FROM f_salary_staff ss
  JOIN user u ON (u.id=ss.user_id)
  LEFT JOIN (
    SELECT staff_id,
      month_year,
      SUM(amount) AS paid_amount
    FROM f_salary
    WHERE month_year='2020-02-29'
    GROUP BY staff_id,month_year
  ) s ON (ss.id=s.staff_id)

我使用了 IFNULL 但这根本不会将 0 转换为任何数字,因此选择甚至没有列出具有 NULL 值的那些。有没有办法在选择时将 NULL 值转换为数值并与其他列进行数值比较?

顺便说一句 .. 下面是两个表的创建表语句。

f_salary_staff

CREATE TABLE `f_salary_staff` (  `id` int(11) NOT NULL AUTO_INCREMENT, `store_id` int(11) NOT NULL,  `user_id` int(11) NOT NULL,  `date_enter` date DEFAULT NULL,  `amount` decimal(12,2) DEFAULT NULL,  `updated` datetime DEFAULT NULL,  `updated_by` int(11) DEFAULT NULL,  `created` datetime DEFAULT NULL,  `created_by` int(11) DEFAULT NULL,  `last_activated` datetime DEFAULT NULL,  `last_inactivated` datetime DEFAULT NULL,  `status` varchar(16) DEFAULT NULL,  PRIMARY KEY (`id`), KEY `store_id` (`store_id`),  KEY `user_id` (`user_id`),  CONSTRAINT `f_salary_staff_ibfk_1` FOREIGN KEY (`store_id`) REFERENCES `store` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,  CONSTRAINT `f_salary_staff_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE )

然后是 f_salary

CREATE TABLE `f_salary` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `staff_id` int(11) NOT NULL,  `amount` decimal(12,2) DEFAULT NULL,  `note` tinytext,  `ref_date` date DEFAULT NULL,  `month_year` date DEFAULT NULL,  `created` datetime DEFAULT NULL,  `created_by` int(11) DEFAULT NULL,  `updated` datetime DEFAULT NULL,  `updated_by` int(11) DEFAULT NULL,  `approved` datetime DEFAULT NULL,  `approved_by` int(11) DEFAULT NULL,  PRIMARY KEY (`id`),  KEY `staff_id` (`staff_id`),  CONSTRAINT `f_salary_ibfk_1` FOREIGN KEY (`staff_id`) REFERENCES `f_salary_staff` (`id`) ON DELETE CASCADE ON UPDATE CASCADE )

希望对需要了解表结构的人有所帮助

【问题讨论】:

  • 我不明白您的查询,“WHERE s.amount > ss.amount”无法正常工作,因为 s.amount 根本不存在
  • 抱歉 .. 应该是 s.paid_amount ... 我该如何编辑问题?
  • 我不懂你的表。我的假设:有一个user 表,它的主键是user_id。有一个staff 表,它的pk 是staff_id。但是:这两者有什么关系? user 表是否有 staff_id 以便每个用户都属于一个员工?表f_salary 有一个staff_id 而不是user_id,所以工资是在员工身上而不是在用户身上?那个员工中的每个用户都得到这个薪水,还是他们自己分配?然后表f_salary_staff 有一个user_id,名字暗示它应该有一个staff_id...
  • ... 请解释一下您的表格。它们代表什么?他们的钥匙是什么?
  • 您好 .. 我已经把 create table 语句供参考 .. 希望对您有所帮助

标签: mysql null comparison numeric ifnull


【解决方案1】:

选择甚至没有列出具有 NULL 值的那些

因为您有一个LEFT JOIN,它被WHERE 子句转换为INNER JOIN
将条件移至 ON 子句。
同样在左连接查询中,您选择列 staff_id 尽管它没有包含在应有的 GROUP BY 子句中。
改为:

SELECT ss.id AS staff_id, u.realname AS realname, ss.amount AS salary_amount, 
COALESCE(s.paid_amount, 0) AS paid_amount,
ss.amount - COALESCE(s.paid_amount, 0)
FROM f_salary_staff ss 
INNER JOIN user u ON (u.id=ss.user_id) 
LEFT JOIN (
  SELECT staff_id, ref_date, SUM(amount) AS paid_amount 
  FROM f_salary 
  WHERE month_year='2020-02-29' 
  GROUP BY staff_id, ref_date
) s ON (ss.id=s.staff_id) AND s.paid_amount > ss.amount

【讨论】:

  • err .. 我的问题是我想将 LEFT JOIN 产生的任何 NULL 值转换为数字 0.00 (s.paid_amount) 以便我可以将它与列 ss.amount .... 进行比较甚至可以将 NULL 变成数字?
  • 这就是 COALESCE 所做的。左连接返回的所有 NULL 在结果中都将是 0。
  • 是的 .. 我确实得到了 0.00 的结果 .. 但是它无法与 ss.amount 列进行比较 ...看看我修复的最新语句 .. 第 5 列产生 NULL : (
  • 试过这个.. s.paid_amount 的原始值为 NULL 的行没有出现:(
  • 使用 COALESCE 不会改变返回的行数,它只是将 NULL 更改为 0。检查您的要求和代码。我的答案中的代码与您发布的问题有关:(1)*为什么您没有得到带有 NULL 的行*,答案是因为您滥用了 LEFT JOIN 和(2)如何使 NULL 显示为 0答案就是 COALESCE。
【解决方案2】:

如果我能很好地理解您的需求,下面的查询应该可以工作:

SELECT t.*
FROM (
  SELECT 
    ss.id AS staff_id, 
    u.realname AS realname, 
    ss.amount AS salary_amount, 
    COALESCE(s.paid_amount, 0) AS paid_amount 
  FROM f_salary_staff ss 
  INNER JOIN user u ON (u.id=ss.user_id) 
  LEFT JOIN (
    SELECT staff_id, ref_date, SUM(amount) AS paid_amount 
    FROM f_salary 
    WHERE month_year='2020-02-29' 
    GROUP BY staff_id, ref_date
  ) s ON (ss.id=s.staff_id) 
) t
WHERE paid_amount > salary_amount

【讨论】:

  • 试过这个......没用......我已经编辑了 select 语句,希望你能更好地理解......只有在第 3 列和第 4 列在数字上都是合法的时才会出现第 5 列..否则它将为 NULL
  • 与您的需求相比,我的查询有什么问题?我错过了什么?
  • Gosfly .. 该声明没有产生任何结果 :( ...我怀疑 COALESCE 只是将 0 用于显示而不是为了使其具有可比性...您还有其他想法吗?
  • 子查询有没有返回什么?
  • Gosfly .. 抱歉 ... 哪个子查询?
【解决方案3】:

感谢 forpas 和 Gosfly .. 显然 COALESCE 或 IFNULL 甚至 IF 不能将 NULL 更改为 NULL 或 NOT NULL 以外的任何其他值 .. 结果仅用于显示,而不是它的真正价值 .. 所以我已将声明改为这样

SELECT
  ss.id AS staff_id,
  u.realname AS realname,
  ss.amount AS salary_amount,
  IFNULL(s.paid_amount,0.00) AS paid_amount,
  IF(s.paid_amount IS NULL,ss.amount,ss.amount-s.paid_amount) AS unpaid_amount
FROM f_salary_staff ss
  JOIN user u ON (u.id=ss.user_id)
  LEFT JOIN (
    SELECT staff_id,
      month_year,
      SUM(amount) AS paid_amount
    FROM f_salary
    WHERE month_year='2020-02-29'
    GROUP BY staff_id,month_year
  ) s ON (ss.id=s.staff_id)  
WHERE ss.amount != s.paid_amount OR s.paid_amount IS NULL

谢谢大家!

【讨论】:

  • IFNULL(s.paid_amount,0.00)COALESCE(s.paid_amount,0.00) 相同,IF(s.paid_amount IS NULL,ss.amount,ss.amount-s.paid_amount)ss.amount - COALESCE(s.paid_amount, 0) 相同,那么有什么区别?另外显然 COALESCE 或 IFNULL 甚至 IF 不能将 NULL 更改为 NULL 或 NOT NULL 以外的任何其他值 是完全错误的。
猜你喜欢
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多