3. 风控交易表金额字段非负校验
任务说明
风控交易表 risk_trade 中,amount 字段理论上不应为负数。本案例编写一条 SQL,找出所有 amount < 0 的异常记录,输出交易ID、金额和发生时间。
表结构与样例数据
为便于独立复现,先建表并插入几条数据(含正常与异常记录):
CREATE TABLE risk_trade (
trade_id VARCHAR(32) NOT NULL,
amount DECIMAL(18,2) NOT NULL,
trade_time DATETIME NOT NULL,
PRIMARY KEY (trade_id)
);
INSERT INTO risk_trade (trade_id, amount, trade_time) VALUES
('T1001', 120.50, '2024-05-01 09:12:00'),
('T1002', -300.00, '2024-05-01 10:05:00'),
('T1003', 88.00, '2024-05-01 11:30:00'),
('T1004', -15.75, '2024-05-01 14:47:00'),
('T1005', 0.00, '2024-05-01 15:20:00');
校验 SQL
核心逻辑:过滤 amount < 0,按发生时间排序,输出三个目标字段。
SELECT
trade_id,
amount,
trade_time
FROM risk_trade
WHERE amount < 0
ORDER BY trade_time;
运行与验证
- 在 MySQL / PostgreSQL 等支持
DECIMAL与DATETIME的数据库中执行上面的建表、插入与查询语句。 - 观察结果集:应只包含
amount为负的记录,且按trade_time升序排列。 - 通过条件:结果中每条记录的
amount均小于 0,且不包含amount >= 0的记录(如 T1001、T1003、T1005)。
基于上述样例数据,查询会返回 T1002 与 T1004 两条记录,字段为 trade_id、amount、trade_time。若结果中出现非负金额,说明过滤条件或字段类型有误,需检查 amount 是否被当作字符串比较。
常见问题
- 金额被存成字符串:若
amount为VARCHAR,< 0会按字符串比较导致误判,应改为数值类型或显式转换CAST(amount AS DECIMAL(18,2)) < 0。 - NULL 值:
amount为 NULL 时不会被< 0命中,如需一并排查可加OR amount IS NULL。 - 时区/时间格式:
trade_time仅用于输出与排序,不影响非负校验逻辑。