MySQL8.0电商金融交易系统SQL实战

SQL 编写

(一)表结构定义(基于 MySQL 8.0+)

1. 产品信息表(product_info)- 存储银行理财 / 商品产品基础信息
字段名 数据类型 约束说明 字段含义
product_id INT PRIMARY KEY AUTO_INCREMENT 产品唯一 ID
product_name VARCHAR(50) NOT NULL UNIQUE 产品名称(如:半年期理财、定期存款、智能手机)
product_type VARCHAR(20) NOT NULL 产品类型(理财 / 存款 / 实物商品 / 虚拟商品)
unit_price DECIMAL(10,2) NOT NULL CHECK (unit_price > 0) 单位价格(理财 / 存款为起购金额,商品为单价)
status TINYINT DEFAULT 1 CHECK (status IN (0,1)) 产品状态(0:下架,1:在售)
create_time DATETIME DEFAULT CURRENT_TIMESTAMP 产品创建时间
2. 购买时间表(purchase_time)- 存储交易时间维度信息
字段名 数据类型 约束说明 字段含义
time_id INT PRIMARY KEY AUTO_INCREMENT 时间记录唯一 ID
purchase_date DATE NOT NULL 交易日期
purchase_hour TINYINT NOT NULL CHECK (purchase_hour BETWEEN 0 AND 23) 交易小时(24 小时制)
week_day TINYINT NOT NULL CHECK (week_day BETWEEN 1 AND 7) 星期(1:周一,7:周日)
quarter TINYINT NOT NULL CHECK (quarter BETWEEN 1 AND 4) 季度
year INT NOT NULL 交易年份
3. 购买数量表(purchase_quantity)- 存储交易数量及关联关系
字段名 数据类型 约束说明 字段含义
quantity_id INT PRIMARY KEY AUTO_INCREMENT 数量记录唯一 ID
user_id INT NOT NULL 购买用户 ID
product_id INT NOT NULL 产品 ID(关联 product_info.product_id)
time_id INT NOT NULL 时间 ID(关联 purchase_time.time_id)
purchase_quantity INT NOT NULL CHECK (purchase_quantity > 0) 购买数量(理财 / 存款为 1,商品为实际购买件数)
order_id VARCHAR(30) NOT NULL UNIQUE 订单 / 交易流水号
FOREIGN KEY (product_id) REFERENCES product_info(product_id) ON UPDATE CASCADE ON DELETE RESTRICT
FOREIGN KEY (time_id) REFERENCES purchase_time(time_id) ON UPDATE CASCADE ON DELETE RESTRICT
4. 金额表(amount_detail)- 存储交易金额明细
字段名 数据类型 约束说明 字段含义
amount_id INT PRIMARY KEY AUTO_INCREMENT 金额记录唯一 ID
order_id VARCHAR(30) NOT NULL 订单 / 交易流水号(关联 purchase_quantity.order_id)
total_amount DECIMAL(12,2) NOT NULL CHECK (total_amount > 0) 交易总金额(unit_price × purchase_quantity)
discount_amount DECIMAL(12,2) DEFAULT 0 CHECK (discount_amount >= 0) 优惠金额
actual_pay DECIMAL(12,2) NOT NULL CHECK (actual_pay >= 0) 实际支付金额(total_amount - discount_amount)
payment_method VARCHAR(20) NOT NULL 支付方式(银行卡 / 微信 / 支付宝 / 现金)
FOREIGN KEY (order_id) REFERENCES purchase_quantity(order_id) ON UPDATE CASCADE ON DELETE CASCADE

(二)测试数据(INSERT 语句)

sql 复制代码
-- 1. 产品信息表数据
INSERT INTO product_info (product_name, product_type, unit_price, status, create_time)
VALUES 
('半年期稳健理财', '理财', 5000.00, 1, '2023-01-10 09:00:00'),
('一年期定期存款', '存款', 1000.00, 1, '2023-01-01 00:00:00'),
('高端智能手机', '实物商品', 6999.00, 1, '2023-02-15 14:30:00'),
('三个月短期理财', '理财', 10000.00, 1, '2023-03-05 10:00:00'),
('无线蓝牙耳机', '实物商品', 399.00, 1, '2023-02-20 11:00:00'),
('虚拟会员年卡', '虚拟商品', 199.00, 1, '2023-04-01 00:00:00'),
('二年期定期存款', '存款', 2000.00, 1, '2023-01-01 00:00:00'),
('智能手表', '实物商品', 1599.00, 1, '2023-03-10 15:00:00'),
('结构性存款A款', '存款', 50000.00, 1, '2023-02-01 09:00:00'),
('云存储套餐', '虚拟商品', 99.00, 1, '2023-04-15 16:00:00');

-- 2. 购买时间表数据
INSERT INTO purchase_time (purchase_date, purchase_hour, week_day, quarter, year)
VALUES 
('2023-05-10', 9, 3, 2, 2023),
('2023-06-15', 14, 5, 2, 2023),
('2023-07-20', 10, 4, 3, 2023),
('2023-08-05', 16, 7, 3, 2023),
('2023-09-12', 11, 2, 3, 2023),
('2023-10-18', 15, 3, 4, 2023),
('2023-11-22', 13, 4, 4, 2023),
('2023-12-03', 10, 7, 4, 2023),
('2024-01-15', 9, 2, 1, 2024),
('2024-02-20', 14, 3, 1, 2024);

-- 3. 购买数量表数据
INSERT INTO purchase_quantity (user_id, product_id, time_id, purchase_quantity, order_id)
VALUES 
(1001, 1, 1, 1, 'TR20230510090001'),
(1002, 3, 2, 1, 'TR20230615140002'),
(1003, 2, 3, 1, 'TR20230720100003'),
(1004, 5, 4, 2, 'TR20230805160004'),
(1005, 4, 5, 1, 'TR20230912110005'),
(1006, 6, 6, 3, 'TR20231018150006'),
(1001, 7, 7, 1, 'TR20231122130007'),
(1002, 8, 8, 1, 'TR20231203100008'),
(1003, 9, 9, 1, 'TR20240115090009'),
(1004, 10, 10, 2, 'TR20240220140010');

-- 4. 金额表数据
INSERT INTO amount_detail (order_id, total_amount, discount_amount, actual_pay, payment_method)
VALUES 
('TR20230510090001', 5000.00, 0.00, 5000.00, '银行卡'),
('TR20230615140002', 6999.00, 200.00, 6799.00, '微信'),
('TR20230720100003', 1000.00, 0.00, 1000.00, '银行卡'),
('TR20230805160004', 798.00, 50.00, 748.00, '支付宝'),
('TR20230912110005', 10000.00, 0.00, 10000.00, '银行卡'),
('TR20231018150006', 597.00, 30.00, 567.00, '微信'),
('TR20231122130007', 2000.00, 0.00, 2000.00, '银行卡'),
('TR20231203100008', 1599.00, 100.00, 1499.00, '支付宝'),
('TR20240115090009', 50000.00, 0.00, 50000.00, '银行卡'),
('TR20240220140010', 198.00, 0.00, 198.00, '微信');

(三)SQL 编写

  • 查询 2023 年各季度的交易总金额、平均单笔交易金额、交易笔数,按季度升序排序。
sql 复制代码
SELECT 
    pt.quarter,
    SUM(ad.actual_pay) AS total_trans_amount,
    ROUND(AVG(ad.actual_pay), 2) AS avg_single_amount,
    COUNT(DISTINCT pq.order_id) AS transaction_count
FROM purchase_quantity pq
JOIN purchase_time pt ON pq.time_id = pt.time_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
WHERE pt.year = 2023
GROUP BY pt.quarter
ORDER BY pt.quarter;
  • 找出购买过 "理财" 类产品且交易金额超过 8000 元的用户 ID、产品名称、实际支付金额及交易日期,按实际支付金额降序排序。
sql 复制代码
SELECT 
    pq.user_id,
    pi.product_name,
    ad.actual_pay,
    pt.purchase_date
FROM purchase_quantity pq
JOIN product_info pi ON pq.product_id = pi.product_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
JOIN purchase_time pt ON pq.time_id = pt.time_id
WHERE 
    pi.product_type = '理财'
    AND ad.actual_pay > 8000
ORDER BY ad.actual_pay DESC;
  • 统计每种支付方式的交易总笔数、总优惠金额、总实际支付金额,筛选出总实际支付金额超过 5000 元的支付方式,按总实际支付金额降序排序。
sql 复制代码
SELECT 
    ad.payment_method,
    COUNT(DISTINCT ad.order_id) AS transaction_count,
    SUM(ad.discount_amount) AS total_discount,
    SUM(ad.actual_pay) AS total_actual_pay
FROM amount_detail ad
GROUP BY ad.payment_method
HAVING SUM(ad.actual_pay) > 5000
ORDER BY total_actual_pay DESC;
  • 查询每周各时段(小时)的交易笔数分布,显示星期、交易小时、交易笔数,按星期升序、交易小时升序排序。
sql 复制代码
SELECT 
    pt.week_day,
    pt.purchase_hour,
    COUNT(DISTINCT pq.order_id) AS transaction_count
FROM purchase_quantity pq
JOIN purchase_time pt ON pq.time_id = pt.time_id
GROUP BY pt.week_day, pt.purchase_hour
ORDER BY pt.week_day, pt.purchase_hour;
  • 找出 2023 年购买商品数量最多的用户(按购买总件数统计),显示用户 ID、总购买件数、总实际支付金额,若有并列则全部列出。
sql 复制代码
WITH user_total_quantity AS (
    SELECT 
        user_id,
        SUM(purchase_quantity) AS total_quantity,
        SUM(ad.actual_pay) AS total_actual_pay
    FROM purchase_quantity pq
    JOIN amount_detail ad ON pq.order_id = ad.order_id
    JOIN purchase_time pt ON pq.time_id = pt.time_id
    WHERE pt.year = 2023
    GROUP BY user_id
),
max_quantity AS (
    SELECT MAX(total_quantity) AS max_qty FROM user_total_quantity
)
SELECT 
    utq.user_id,
    utq.total_quantity,
    utq.total_actual_pay
FROM user_total_quantity utq
JOIN max_quantity mq ON utq.total_quantity = mq.max_qty
ORDER BY utq.user_id;
  • 查询每种产品的销售情况:产品名称、产品类型、销售总件数、总实际收入,按总实际收入降序排序,仅显示在售产品(status=1)。
sql 复制代码
SELECT 
    pi.product_name,
    pi.product_type,
    SUM(pq.purchase_quantity) AS total_sales_quantity,
    SUM(ad.actual_pay) AS total_actual_income
FROM product_info pi
JOIN purchase_quantity pq ON pi.product_id = pq.product_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
WHERE pi.status = 1
GROUP BY pi.product_id, pi.product_name, pi.product_type
ORDER BY total_actual_income DESC;
  • 编写 SQL 语句,计算 2023 年每个月的交易增长率(环比),显示月份、当月交易总金额、上月交易总金额、增长率(保留 1 位小数),增长率公式:(当月 - 上月)/ 上月 ×100%。
sql 复制代码
WITH monthly_trans AS (
    SELECT 
        pt.year,
        MONTH(pt.purchase_date) AS month,
        SUM(ad.actual_pay) AS monthly_total
    FROM purchase_quantity pq
    JOIN purchase_time pt ON pq.time_id = pt.time_id
    JOIN amount_detail ad ON pq.order_id = ad.order_id
    WHERE pt.year = 2023
    GROUP BY pt.year, MONTH(pt.purchase_date)
)
SELECT 
    current.month,
    current.monthly_total AS current_month_total,
    COALESCE(prev.monthly_total, 0) AS prev_month_total,
    ROUND(
        CASE WHEN COALESCE(prev.monthly_total, 0) = 0 THEN 0 
        ELSE (current.monthly_total - prev.monthly_total)/prev.monthly_total * 100 
        END, 1
    ) AS growth_rate
FROM monthly_trans current
LEFT JOIN monthly_trans prev ON current.month = prev.month + 1
ORDER BY current.month;
  • 查询同时购买了 "实物商品" 和 "虚拟商品" 的用户 ID,以及两类商品的交易总金额(分别显示),按用户 ID 升序排序。
sql 复制代码
WITH physical_user AS (
    SELECT DISTINCT pq.user_id
    FROM purchase_quantity pq
    JOIN product_info pi ON pq.product_id = pi.product_id
    WHERE pi.product_type = '实物商品'
),
virtual_user AS (
    SELECT DISTINCT pq.user_id
    FROM purchase_quantity pq
    JOIN product_info pi ON pq.product_id = pi.product_id
    WHERE pi.product_type = '虚拟商品'
)
SELECT 
    pu.user_id,
    COALESCE(SUM(CASE WHEN pi.product_type = '实物商品' THEN ad.actual_pay ELSE 0 END), 0) AS physical_total,
    COALESCE(SUM(CASE WHEN pi.product_type = '虚拟商品' THEN ad.actual_pay ELSE 0 END), 0) AS virtual_total
FROM physical_user pu
JOIN virtual_user vu ON pu.user_id = vu.user_id
JOIN purchase_quantity pq ON pu.user_id = pq.user_id
JOIN product_info pi ON pq.product_id = pi.product_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
GROUP BY pu.user_id
ORDER BY pu.user_id;
  • 统计 2023 年各星期的平均每笔交易金额,筛选出平均金额高于全年平均每笔交易金额的星期,按平均金额降序排序。
sql 复制代码
WITH week_avg_amount AS (
    SELECT 
        pt.week_day,
        ROUND(AVG(ad.actual_pay), 2) AS week_avg_pay
    FROM purchase_quantity pq
    JOIN purchase_time pt ON pq.time_id = pt.time_id
    JOIN amount_detail ad ON pq.order_id = ad.order_id
    WHERE pt.year = 2023
    GROUP BY pt.week_day
),
year_avg_amount AS (
    SELECT ROUND(AVG(actual_pay), 2) AS year_avg_pay
    FROM amount_detail ad
    JOIN purchase_quantity pq ON ad.order_id = pq.order_id
    JOIN purchase_time pt ON pq.time_id = pt.time_id
    WHERE pt.year = 2023
)
SELECT 
    wa.week_day,
    wa.week_avg_pay
FROM week_avg_amount wa
JOIN year_avg_amount ya ON wa.week_avg_pay > ya.year_avg_pay
ORDER BY wa.week_avg_pay DESC;
  • 创建一个视图v_high_value_transaction,包含订单号、用户 ID、产品名称、交易日期、实际支付金额、支付方式,要求:实际支付金额≥5000 元、交易年份为 2023 年、产品类型为 "理财" 或 "存款",视图数据按交易日期降序排序。
sql 复制代码
CREATE VIEW v_high_value_transaction AS
SELECT 
    pq.order_id,
    pq.user_id,
    pi.product_name,
    pt.purchase_date,
    ad.actual_pay,
    ad.payment_method
FROM purchase_quantity pq
JOIN product_info pi ON pq.product_id = pi.product_id
JOIN purchase_time pt ON pq.time_id = pt.time_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
WHERE 
    ad.actual_pay >= 5000
    AND pt.year = 2023
    AND pi.product_type IN ('理财', '存款')
ORDER BY pt.purchase_date DESC;
  • 查询 2023 年第三季度(7-9 月)各产品类型的交易笔数、总金额,按产品类型升序排序。
sql 复制代码
SELECT 
    pi.product_type,
    COUNT(DISTINCT pq.order_id) AS transaction_count,
    SUM(ad.actual_pay) AS total_amount
FROM purchase_quantity pq
JOIN product_info pi ON pq.product_id = pi.product_id
JOIN purchase_time pt ON pq.time_id = pt.time_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
WHERE pt.year = 2023 AND pt.quarter = 3
GROUP BY pi.product_type
ORDER BY pi.product_type;
  • 找出实际支付金额排名前 3 的订单对应的用户 ID、产品名称、交易时间(日期 + 小时)、支付方式,若有并列则顺延。
sql 复制代码
WITH order_rank AS (
    SELECT 
        pq.user_id,
        pi.product_name,
        CONCAT(pt.purchase_date, ' ', pt.purchase_hour, ':00') AS transaction_time,
        ad.payment_method,
        ad.actual_pay,
        DENSE_RANK() OVER (ORDER BY ad.actual_pay DESC) AS pay_rank
    FROM purchase_quantity pq
    JOIN product_info pi ON pq.product_id = pi.product_id
    JOIN purchase_time pt ON pq.time_id = pt.time_id
    JOIN amount_detail ad ON pq.order_id = ad.order_id
)
SELECT 
    user_id,
    product_name,
    transaction_time,
    payment_method,
    actual_pay
FROM order_rank
WHERE pay_rank <= 3
ORDER BY actual_pay DESC, user_id;
  • 统计每个用户的购买频次(交易笔数)和平均每笔交易金额,筛选出购买频次≥2 次的用户,按平均每笔金额降序排序。
sql 复制代码
SELECT 
    pq.user_id,
    COUNT(DISTINCT pq.order_id) AS purchase_frequency,
    ROUND(AVG(ad.actual_pay), 2) AS avg_single_pay
FROM purchase_quantity pq
JOIN amount_detail ad ON pq.order_id = ad.order_id
GROUP BY pq.user_id
HAVING COUNT(DISTINCT pq.order_id) >= 2
ORDER BY avg_single_pay DESC;
  • 查询没有享受优惠(discount_amount=0)的交易中,各产品类型的交易总金额和占比(占无优惠交易总金额的百分比,保留 1 位小数)。
sql 复制代码
WITH no_discount_total AS (
    SELECT SUM(actual_pay) AS total_no_discount
    FROM amount_detail
    WHERE discount_amount = 0
)
SELECT 
    pi.product_type,
    SUM(ad.actual_pay) AS type_total,
    ROUND((SUM(ad.actual_pay)/ndt.total_no_discount)*100, 1) AS type_ratio
FROM product_info pi
JOIN purchase_quantity pq ON pi.product_id = pq.product_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
JOIN no_discount_total ndt
WHERE ad.discount_amount = 0
GROUP BY pi.product_type, ndt.total_no_discount
ORDER BY type_ratio DESC;
  • 编写 SQL 语句,更新 "高端智能手机"(product_name)的优惠规则:后续交易的优惠金额调整为单位价格的 5%(需先查询单位价格,再更新金额表中未发生的交易,此处假设模拟更新现有符合条件的订单)。
sql 复制代码
-- 1. 查询高端智能手机的单位价格
SELECT unit_price FROM product_info WHERE product_name = '高端智能手机';

-- 2. 模拟更新现有符合条件的订单(实际场景为后续交易,此处更新现有订单示例)
UPDATE amount_detail ad
JOIN purchase_quantity pq ON ad.order_id = pq.order_id
JOIN product_info pi ON pq.product_id = pi.product_id
SET 
    ad.discount_amount = pi.unit_price * 0.05,
    ad.actual_pay = ad.total_amount - (pi.unit_price * 0.05)
WHERE pi.product_name = '高端智能手机';
  • 查询 2023 年各月份的交易高峰时段(交易笔数最多的小时),显示月份、高峰小时、交易笔数,若有多个高峰时段则全部列出。
sql 复制代码
WITH monthly_hour_count AS (
    SELECT 
        pt.year,
        MONTH(pt.purchase_date) AS month,
        pt.purchase_hour,
        COUNT(DISTINCT pq.order_id) AS hour_count
    FROM purchase_quantity pq
    JOIN purchase_time pt ON pq.time_id = pt.time_id
    WHERE pt.year = 2023
    GROUP BY pt.year, MONTH(pt.purchase_date), pt.purchase_hour
),
monthly_max_count AS (
    SELECT 
        month,
        MAX(hour_count) AS max_hour_count
    FROM monthly_hour_count
    GROUP BY month
)
SELECT 
    mhc.month,
    mhc.purchase_hour AS peak_hour,
    mhc.hour_count
FROM monthly_hour_count mhc
JOIN monthly_max_count mmc ON mhc.month = mmc.month AND mhc.hour_count = mmc.max_hour_count
ORDER BY mhc.month, mhc.purchase_hour;
  • 统计每种产品的复购率(购买该产品的用户中,有多次购买记录的用户占比,保留 1 位小数),复购定义为同一用户对同一产品购买≥2 次(基于现有数据,若无复购则显示 0%)。
sql 复制代码
WITH product_user_purchase AS (
    SELECT 
        pi.product_id,
        pi.product_name,
        pq.user_id,
        COUNT(DISTINCT pq.order_id) AS purchase_times
    FROM product_info pi
    JOIN purchase_quantity pq ON pi.product_id = pq.product_id
    GROUP BY pi.product_id, pi.product_name, pq.user_id
),
product_user_stats AS (
    SELECT 
        product_id,
        product_name,
        COUNT(DISTINCT user_id) AS total_user,
        COUNT(DISTINCT CASE WHEN purchase_times >= 2 THEN user_id ELSE NULL END) AS repeat_user
    FROM product_user_purchase
    GROUP BY product_id, product_name
)
SELECT 
    product_name,
    ROUND(CASE WHEN total_user = 0 THEN 0 ELSE (repeat_user/total_user)*100 END, 1) AS repurchase_rate
FROM product_user_stats
ORDER BY repurchase_rate DESC;
  • 查询 2023 年使用微信支付的交易中,各季度的总金额和平均优惠金额,按季度升序排序。
sql 复制代码
SELECT 
    pt.quarter,
    SUM(ad.actual_pay) AS total_wechat_pay,
    ROUND(AVG(ad.discount_amount), 2) AS avg_wechat_discount
FROM purchase_quantity pq
JOIN purchase_time pt ON pq.time_id = pt.time_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
WHERE pt.year = 2023 AND ad.payment_method = '微信'
GROUP BY pt.quarter
ORDER BY pt.quarter;
  • 找出购买了 "一年期定期存款" 但未购买任何 "理财" 类产品的用户 ID,按用户 ID 升序排序。
sql 复制代码
SELECT DISTINCT pq.user_id
FROM purchase_quantity pq
JOIN product_info pi ON pq.product_id = pi.product_id
WHERE pi.product_name = '一年期定期存款'
AND pq.user_id NOT IN (
    SELECT DISTINCT pq2.user_id
    FROM purchase_quantity pq2
    JOIN product_info pi2 ON pq2.product_id = pi2.product_id
    WHERE pi2.product_type = '理财'
)
ORDER BY pq.user_id;
  • 编写 SQL 语句,计算各产品类型的客单价(总实际收入 / 购买用户数,保留 2 位小数),按客单价降序排序。
sql 复制代码
SELECT 
    pi.product_type,
    ROUND(SUM(ad.actual_pay)/COUNT(DISTINCT pq.user_id), 2) AS customer_unit_price
FROM product_info pi
JOIN purchase_quantity pq ON pi.product_id = pq.product_id
JOIN amount_detail ad ON pq.order_id = ad.order_id
GROUP BY pi.product_type
ORDER BY customer_unit_price DESC;
相关推荐
amao99882 小时前
数据库管理系统DBMS
数据库·oracle
wdfk_prog2 小时前
Ubuntu 虚拟机根文件系统损坏故障的深度分析与修复
linux·数据库·ubuntu
DemonAvenger2 小时前
Redis发布订阅模式:打造实时消息通信系统的实践指南
数据库·redis·性能优化
luoluoal3 小时前
基于python的反爬虫技术的研究(源码+文档)
开发语言·python·mysql
sc.溯琛3 小时前
MySQL 入门实验:环境搭建与基础操作全攻略
数据库·mysql
徐子童3 小时前
索引的分类和创建
mysql·面试·基础·索引
JIngJaneIL3 小时前
基于java+ vue建筑材料管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
一 乐3 小时前
办公系统|基于springboot + vueOA办公管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
麦麦鸡腿堡3 小时前
MySQL表的操作指令与常用数值类型
数据库·mysql