如何使用PHP或SQL计算SQL列中字符串语句内的数字之和?
从M-PESA交易字符串中提取数字并求和的解决方案
针对你给出的这类包含M-PESA交易信息的字符串,我分别提供PHP和SQL两种实现方案,帮你提取其中的货币数字并完成求和:
PHP实现方案
PHP里我们可以借助正则表达式精准提取目标数字,再进行累加。考虑到你的字符串里的金额都是以Ksh开头的带小数格式,我们可以专门匹配这类数字,避免把日期里的整数误算进去:
<?php // 示例交易字符串 $transactionText = "MEL1INFA73 Confirmed. Ksh29.00 sent to Safaricom Offers for account Tunukiwa on 21/5/18 at 3:29 AM New M-PESA balance is Ksh5.50. Transaction cost, Ksh0.00."; // 正则匹配所有Ksh后面的小数数字 preg_match_all('/Ksh(\d+\.\d+)/', $transactionText, $matches); $sum = 0.00; // 遍历匹配到的数字并累加 foreach ($matches[1] as $amount) { $sum += (float)$amount; } // 输出结果:34.50 echo "所有金额总和:Ksh" . number_format($sum, 2); ?>
说明
- 正则
/Ksh(\d+\.\d+)/会精准捕获Ksh后跟的小数金额,括号里的分组是我们需要的数字部分; - 如果你的字符串里还有不带小数点的整数金额,可以把正则调整为
/Ksh(\d+(\.\d+)?)/,兼容整数和小数格式; - 使用
number_format可以让输出的金额保持两位小数,更符合货币格式。
SQL实现方案
SQL的实现会根据你使用的数据库略有不同,下面分别给出MySQL和PostgreSQL的常用方案:
MySQL方案
MySQL没有原生的全局正则匹配提取函数,我们可以自定义一个存储函数来循环提取并累加金额:
-- 创建自定义求和函数 DELIMITER // CREATE FUNCTION calculate_ksh_total(input_str TEXT) RETURNS DECIMAL(10,2) DETERMINISTIC BEGIN DECLARE total DECIMAL(10,2) DEFAULT 0.00; DECLARE ksh_pos INT; DECLARE amount_start INT; DECLARE amount_end INT; DECLARE amount_str VARCHAR(20); -- 查找第一个Ksh的位置 SET ksh_pos = LOCATE('Ksh', input_str); WHILE ksh_pos > 0 DO SET amount_start = ksh_pos + 3; -- 跳过Ksh三个字符 -- 找到金额后面的第一个空格位置 SET amount_end = LOCATE(' ', input_str, amount_start); -- 如果是字符串末尾,就取到最后 IF amount_end = 0 THEN SET amount_end = CHAR_LENGTH(input_str) + 1; END IF; -- 截取金额字符串 SET amount_str = SUBSTRING(input_str, amount_start, amount_end - amount_start); -- 验证是否是合法小数,避免错误累加 IF amount_str REGEXP '^\\d+\\.\\d+$' THEN SET total = total + CAST(amount_str AS DECIMAL(10,2)); END IF; -- 截断字符串,继续查找下一个Ksh SET input_str = SUBSTRING(input_str, amount_end); SET ksh_pos = LOCATE('Ksh', input_str); END WHILE; RETURN total; END // DELIMITER ; -- 使用函数求和(假设表名为transactions,字段名为transaction_note) SELECT calculate_ksh_total(transaction_note) AS total_transaction_amount FROM transactions;
PostgreSQL方案
PostgreSQL支持原生的全局正则匹配和数组展开,实现起来更简洁:
-- 假设表名为transactions,字段名为transaction_details SELECT SUM(CAST(amount AS DECIMAL(10,2))) AS total_amount FROM ( -- 全局匹配所有Ksh后面的金额,展开为行 SELECT unnest(regexp_matches(transaction_details, 'Ksh(\\d+\\.\\d+)', 'g')) AS amount FROM transactions ) AS extracted_amounts;
说明
- 两种SQL方案都专门针对
Ksh开头的金额进行提取,避免了日期、时间里的数字干扰; - 如果你的字符串格式有变化,可以调整正则表达式或者函数里的定位逻辑来适配。
内容的提问来源于stack exchange,提问作者Ronald
相关产品推荐
相关产品推荐

