本文目录导读:

- SQL 脚本 (最常用,用于数据库直接汇总)
- Python 脚本 (使用 Pandas 处理数据)
- Shell/Bash 脚本 (从日志或CSV文件汇总)
- Node.js 脚本 (使用 Sequelize ORM)
- 选择合适的方案
- 注意要点
SQL 脚本 (最常用,用于数据库直接汇总)
适用于:报表工具、数据库任务、定时任务。
-- 1. 按日期统计每日订单汇总
SELECT
DATE(order_date) AS report_date,
COUNT(order_id) AS total_orders,
SUM(order_amount) AS total_amount,
AVG(order_amount) AS avg_order_amount,
COUNT(DISTINCT user_id) AS unique_buyers,
SUM(IF(order_status = 'completed', 1, 0)) AS completed_orders,
SUM(IF(order_status = 'cancelled', 1, 0)) AS cancelled_orders
FROM orders
WHERE order_date >= '2023-01-01'
AND order_date < '2023-12-31'
GROUP BY DATE(order_date)
ORDER BY report_date DESC;
-- 2. 按产品类别统计
SELECT
p.category,
COUNT(oi.order_id) AS order_count,
SUM(oi.quantity) AS total_quantity,
SUM(oi.subtotal) AS total_revenue,
ROUND(AVG(oi.subtotal), 2) AS avg_revenue_per_order
FROM order_items oi
INNER JOIN products p ON oi.product_id = p.product_id
GROUP BY p.category
ORDER BY total_revenue DESC;
-- 3. 月度汇总(包含上期比较)
SELECT
DATE_FORMAT(order_date, '%Y-%m') AS month,
COUNT(order_id) AS orders,
SUM(order_amount) AS revenue,
LAG(SUM(order_amount), 1) OVER (ORDER BY DATE_FORMAT(order_date, '%Y-%m')) AS prev_month_revenue,
ROUND((SUM(order_amount) - LAG(SUM(order_amount), 1) OVER (
ORDER BY DATE_FORMAT(order_date, '%Y-%m')
)) / LAG(SUM(order_amount), 1) OVER (
ORDER BY DATE_FORMAT(order_date, '%Y-%m')
) * 100, 2) AS month_over_month_growth
FROM orders
GROUP BY month
ORDER BY month DESC;
Python 脚本 (使用 Pandas 处理数据)
适用于:从多个数据源取数、需要复杂数据清洗、生成 Excel/CSV 报表。
import pandas as pd
from datetime import datetime, timedelta
# ========== 模拟数据(实际从数据库读取) ==========
# 示例:从CSV或DB读取
# df = pd.read_sql("SELECT * FROM orders", engine)
# 模拟订单数据
data = {
'order_id': [1, 2, 3, 4, 5],
'user_id': [101, 102, 101, 103, 102],
'order_date': ['2023-06-01', '2023-06-01', '2023-06-02', '2023-06-02', '2023-06-03'],
'order_amount': [100.0, 250.0, 300.0, 150.0, 200.0],
'order_status': ['completed', 'completed', 'completed', 'cancelled', 'completed']
}
df = pd.DataFrame(data)
df['order_date'] = pd.to_datetime(df['order_date'])
# ========== 核心汇总函数 ==========
def generate_order_summary(df, period='day'):
"""
生成订单汇总报表
:param df: 原始订单DataFrame
:param period: 汇总粒度 'day', 'week', 'month', 'quarter'
:return: 汇总后的DataFrame
"""
# 创建时间分组列
if period == 'day':
df['group_date'] = df['order_date'].dt.date
elif period == 'week':
df['group_date'] = df['order_date'].dt.isocalendar().week.astype(str) + '-' + df['order_date'].dt.year.astype(str)
elif period == 'month':
df['group_date'] = df['order_date'].dt.to_period('M')
elif period == 'quarter':
df['group_date'] = df['order_date'].dt.to_period('Q')
elif period == 'year':
df['group_date'] = df['order_date'].dt.year
# 汇总计算
summary = df.groupby('group_date').agg(
订单总数=('order_id', 'count'),
总金额=('order_amount', 'sum'),
平均订单金额=('order_amount', 'mean'),
最大订单金额=('order_amount', 'max'),
最小订单金额=('order_amount', 'min'),
独立买家数=('user_id', 'nunique'),
完成订单数=('order_status', lambda x: (x == 'completed').sum()),
取消订单数=('order_status', lambda x: (x == 'cancelled').sum())
).reset_index()
# 添加计算字段
summary['完成率'] = (summary['完成订单数'] / summary['订单总数'] * 100).round(2)
summary['取消率'] = (summary['取消订单数'] / summary['订单总数'] * 100).round(2)
# 排序
summary = summary.sort_values('group_date', ascending=False).reset_index(drop=True)
return summary
# ========== 生成并输出报表 ==========
day_summary = generate_order_summary(df, 'day')
month_summary = generate_order_summary(df, 'month')
print("=== 日报表 ===")
print(day_summary)
print("\n=== 月报表 ===")
print(month_summary)
# 导出到Excel
with pd.ExcelWriter('订单汇总报表.xlsx') as writer:
day_summary.to_excel(writer, sheet_name='日报表', index=False)
month_summary.to_excel(writer, sheet_name='月报表', index=False)
print("\n✅ 报表已导出到 '订单汇总报表.xlsx'")
# ========== 可选:生成趋势图 ==========
import matplotlib.pyplot as plt
plt.figure(figsize=(12, 6))
plt.plot(day_summary['group_date'], day_summary['总金额'], marker='o', label='每日销售额')'订单金额趋势')
plt.xlabel('日期')
plt.ylabel('金额')
plt.xticks(rotation=45)
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('订单趋势图.png')
Shell/Bash 脚本 (从日志或CSV文件汇总)
适用于:Linux服务器环境中,快速处理文本日志或CSV文件。
#!/bin/bash
# 订单汇总报表生成脚本
# 假设订单文件格式:order_id,user_id,date,amount,status
# 示例:1001,101,2023-06-01,250.00,completed
INPUT_FILE="orders.csv"
OUTPUT_FILE="order_summary_report.txt"
# 检查输入文件
if [ ! -f "$INPUT_FILE" ]; then
echo "错误:找不到输入文件 $INPUT_FILE"
exit 1
fi
echo "=== 订单汇总报表 ===" > "$OUTPUT_FILE"
echo "生成时间:$(date '+%Y-%m-%d %H:%M:%S')" >> "$OUTPUT_FILE"
echo "===========================" >> "$OUTPUT_FILE"
# 1. 基本统计
total_orders=$(awk -F',' 'NR>1 {count++} END {print count}' "$INPUT_FILE")
total_amount=$(awk -F',' 'NR>1 {sum+=$4} END {printf "%.2f", sum}' "$INPUT_FILE")
avg_amount=$(awk -F',' 'NR>1 {sum+=$4; count++} END {printf "%.2f", sum/count}' "$INPUT_FILE")
echo "订单总数:$total_orders" >> "$OUTPUT_FILE"
echo "总金额:$total_amount" >> "$OUTPUT_FILE"
echo "平均金额:$avg_amount" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# 2. 按日期统计日汇总
echo "=== 每日汇总 ===" >> "$OUTPUT_FILE"
awk -F',' 'NR>1 {
date=$3;
count[date]++;
sum[date]+=$4;
} END {
for(d in count) {
printf "%s | 订单数: %d | 金额: %.2f\n", d, count[d], sum[d]
}
}' "$INPUT_FILE" | sort >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# 3. 按状态统计
echo "=== 订单状态分布 ===" >> "$OUTPUT_FILE"
awk -F',' 'NR>1 {
status=$5;
status_count[status]++;
} END {
for(s in status_count) {
printf "%s: %d单 (%.2f%%)\n", s, status_count[s], status_count[s]/total*100
}
}' "$INPUT_FILE" total=$total_orders >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
# 4. 按客户统计(Top 10)
echo "=== Top 10 客户(按订单金额) ===" >> "$OUTPUT_FILE"
awk -F',' 'NR>1 {
user=$2;
amount=$4;
user_sum[user]+=amount;
user_count[user]++;
} END {
for(u in user_sum) {
printf "%s | %d单 | %.2f元\n", u, user_count[u], user_sum[u]
}
}' "$INPUT_FILE" | sort -t'|' -k3 -rn | head -10 >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo "✅ 报表已生成:$OUTPUT_FILE"
Node.js 脚本 (使用 Sequelize ORM)
适用于:Node.js 后端应用中生成报表。
const { Sequelize, DataTypes } = require('sequelize');
const ExcelJS = require('exceljs');
// 数据库连接配置
const sequelize = new Sequelize('database', 'username', 'password', {
host: 'localhost',
dialect: 'mysql'
});
// 定义 Order 模型
const Order = sequelize.define('Order', {
id: { type: DataTypes.INTEGER, primaryKey: true },
userId: DataTypes.INTEGER,
totalAmount: DataTypes.DECIMAL(10, 2),
status: DataTypes.STRING,
createdAt: DataTypes.DATE
}, { tableName: 'orders', timestamps: false });
// ========== 生成汇总报表 ==========
async function generateOrderSummaryReport() {
try {
// 1. 按日期分组汇总
const dailySummary = await Order.findAll({
attributes: [
[sequelize.fn('DATE', sequelize.col('createdAt')), 'date'],
[sequelize.fn('COUNT', sequelize.col('id')), 'orderCount'],
[sequelize.fn('SUM', sequelize.col('totalAmount')), 'totalAmount'],
[sequelize.fn('AVG', sequelize.col('totalAmount')), 'avgAmount'],
[sequelize.fn('COUNT', sequelize.fn('DISTINCT', sequelize.col('userId'))), 'uniqueUsers']
],
group: [sequelize.fn('DATE', sequelize.col('createdAt'))],
order: [[sequelize.fn('DATE', sequelize.col('createdAt')), 'DESC']],
raw: true
});
// 2. 按月份汇总(消费趋势)
const monthlySummary = await Order.findAll({
attributes: [
[sequelize.fn('DATE_FORMAT', sequelize.col('createdAt'), '%Y-%m'), 'month'],
[sequelize.fn('COUNT', sequelize.col('id')), 'orderCount'],
[sequelize.fn('SUM', sequelize.col('totalAmount')), 'totalAmount']
],
where: { status: 'completed' },
group: [sequelize.fn('DATE_FORMAT', sequelize.col('createdAt'), '%Y-%m')],
order: [[sequelize.fn('DATE_FORMAT', sequelize.col('createdAt'), '%Y-%m'), 'DESC']],
raw: true
});
// 3. 状态分布
const statusDistribution = await Order.findAll({
attributes: [
'status',
[sequelize.fn('COUNT', sequelize.col('id')), 'count'],
[sequelize.fn('SUM', sequelize.col('totalAmount')), 'totalAmount']
],
group: ['status'],
raw: true
});
// 创建 Excel 报表
const workbook = new ExcelJS.Workbook();
// 添加每日汇总工作表
const dailySheet = workbook.addWorksheet('每日汇总');
dailySheet.columns = [
{ header: '日期', key: 'date', width: 15 },
{ header: '订单数', key: 'orderCount', width: 12 },
{ header: '总金额', key: 'totalAmount', width: 15 },
{ header: '平均金额', key: 'avgAmount', width: 12 },
{ header: '独立用户', key: 'uniqueUsers', width: 12 }
];
dailySheet.addRows(dailySummary);
// 添加月度趋势工作表
const monthlySheet = workbook.addWorksheet('月度趋势');
monthlySheet.columns = [
{ header: '月份', key: 'month', width: 10 },
{ header: '订单数', key: 'orderCount', width: 12 },
{ header: '总金额', key: 'totalAmount', width: 15 }
];
monthlySheet.addRows(monthlySummary);
// 添加状态分布工作表
const statusSheet = workbook.addWorksheet('状态分布');
statusSheet.columns = [
{ header: '状态', key: 'status', width: 15 },
{ header: '订单数', key: 'count', width: 12 },
{ header: '总金额', key: 'totalAmount', width: 15 }
];
statusSheet.addRows(statusDistribution);
// 保存文件
const filename = `订单汇总报表_${new Date().toISOString().slice(0,10)}.xlsx`;
await workbook.xlsx.writeFile(filename);
console.log(`✅ 报表已生成: ${filename}`);
} catch (error) {
console.error('生成报表失败:', error);
} finally {
await sequelize.close();
}
}
// 执行
generateOrderSummaryReport();
选择合适的方案
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 数据库直接跑报表 | SQL | 无需额外工具,性能最好 |
| 需要复杂处理/多数据源 | Python | Pandas 强大,易于扩展 |
| Linux服务器快速处理 | Bash | 轻量,依赖少 |
| Node.js 后端集成 | Node.js | 与现有代码无缝整合 |
| 需要动态可视化 | Python + Matplotlib | 可生成图表 |
注意要点
- 数据量大时:考虑分页查询、使用索引、限制时间范围
- 性能优化:定期对订单表的
order_date和status字段建立索引 - 定时任务:使用 cron(Linux) 或 任务调度器 定期自动执行脚本
- 异常处理:加入重试机制、记录错误日志
- 数据校验:对汇总结果进行交叉验证,确保准确性
根据您的具体需求(如数据规模、技术栈、报表格式),选择最适合的实现方式,如果需要针对特定场景的更多细节,欢迎进一步说明。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播