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;

运行与验证

  1. 在 MySQL / PostgreSQL 等支持 DECIMAL 与 DATETIME 的数据库中执行上面的建表、插入与查询语句。
  2. 观察结果集:应只包含 amount 为负的记录,且按 trade_time 升序排列。
  3. 通过条件:结果中每条记录的 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 仅用于输出与排序,不影响非负校验逻辑。