上传源代码版本
This commit is contained in:
12
.trae/specs/dashboard_query_sql/checklist.md
Normal file
12
.trae/specs/dashboard_query_sql/checklist.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# 数据看板查询逻辑分析 - 验证清单
|
||||
|
||||
- [x] 验证当前查询逻辑的理解是否正确
|
||||
- [x] 验证 MySQL 语句是否完整覆盖所有过滤条件
|
||||
- [x] 验证 MySQL 语句是否正确计算所有统计数据
|
||||
- [x] 验证 MySQL 语句的性能是否优于当前实现
|
||||
- [x] 验证索引建议是否合理
|
||||
- [x] 验证文档是否完整且可读
|
||||
- [x] 验证 MySQL 语句是否可以直接在数据库中执行
|
||||
- [x] 验证统计结果是否与当前实现一致
|
||||
- [x] 验证性能优化建议是否可行
|
||||
- [x] 验证所有测试要求是否满足
|
||||
262
.trae/specs/dashboard_query_sql/mysql_statements.md
Normal file
262
.trae/specs/dashboard_query_sql/mysql_statements.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# 数据看板查询 MySQL 语句
|
||||
|
||||
## 1. 提单号预报查询
|
||||
|
||||
### 1.1 基本查询语句
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
l.BillOfLadingNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
(SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - (SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplacePendingCount,
|
||||
(SELECT MIN(h.ReceiptTime)
|
||||
FROM arrival_handover_forms h
|
||||
WHERE h.HandoverNumber = l.BillOfLadingNumber
|
||||
OR h.HandoverNumber = l.MasterPackageNumber) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = :billOfLadingNumber OR :billOfLadingNumber IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = :masterPackageNumber OR :masterPackageNumber IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= :endDate OR :endDate IS NULL)
|
||||
GROUP BY
|
||||
l.BillOfLadingNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
### 1.2 优化版本(使用子查询优化扫描记录统计)
|
||||
|
||||
```sql
|
||||
WITH scan_summary AS (
|
||||
SELECT
|
||||
NeutralWaybillNumber,
|
||||
COUNT(*) AS ReturnedLabelCount
|
||||
FROM
|
||||
label_scan_history
|
||||
WHERE
|
||||
Result = 0
|
||||
GROUP BY
|
||||
NeutralWaybillNumber
|
||||
),
|
||||
arrival_summary AS (
|
||||
SELECT
|
||||
HandoverNumber,
|
||||
MIN(ReceiptTime) AS MinReceiptTime
|
||||
FROM
|
||||
arrival_handover_forms
|
||||
GROUP BY
|
||||
HandoverNumber
|
||||
)
|
||||
SELECT
|
||||
l.BillOfLadingNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplacePendingCount,
|
||||
COALESCE(a.MinReceiptTime, b.MinReceiptTime) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
LEFT JOIN
|
||||
scan_summary s ON l.NeutralWaybillNumber = s.NeutralWaybillNumber
|
||||
LEFT JOIN
|
||||
arrival_summary a ON l.BillOfLadingNumber = a.HandoverNumber
|
||||
LEFT JOIN
|
||||
arrival_summary b ON l.MasterPackageNumber = b.HandoverNumber
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = :billOfLadingNumber OR :billOfLadingNumber IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = :masterPackageNumber OR :masterPackageNumber IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= :endDate OR :endDate IS NULL)
|
||||
GROUP BY
|
||||
l.BillOfLadingNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
## 2. 大箱号预报查询
|
||||
|
||||
### 2.1 基本查询语句
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
l.MasterPackageNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
(SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - (SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplacePendingCount,
|
||||
(SELECT MIN(h.ReceiptTime)
|
||||
FROM arrival_handover_forms h
|
||||
WHERE h.HandoverNumber = l.BillOfLadingNumber
|
||||
OR h.HandoverNumber = l.MasterPackageNumber) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = :billOfLadingNumber OR :billOfLadingNumber IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = :masterPackageNumber OR :masterPackageNumber IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= :endDate OR :endDate IS NULL)
|
||||
GROUP BY
|
||||
l.MasterPackageNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
### 2.2 优化版本(使用子查询优化扫描记录统计)
|
||||
|
||||
```sql
|
||||
WITH scan_summary AS (
|
||||
SELECT
|
||||
NeutralWaybillNumber,
|
||||
COUNT(*) AS ReturnedLabelCount
|
||||
FROM
|
||||
label_scan_history
|
||||
WHERE
|
||||
Result = 0
|
||||
GROUP BY
|
||||
NeutralWaybillNumber
|
||||
),
|
||||
arrival_summary AS (
|
||||
SELECT
|
||||
HandoverNumber,
|
||||
MIN(ReceiptTime) AS MinReceiptTime
|
||||
FROM
|
||||
arrival_handover_forms
|
||||
GROUP BY
|
||||
HandoverNumber
|
||||
)
|
||||
SELECT
|
||||
l.MasterPackageNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplacePendingCount,
|
||||
COALESCE(a.MinReceiptTime, b.MinReceiptTime) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
LEFT JOIN
|
||||
scan_summary s ON l.NeutralWaybillNumber = s.NeutralWaybillNumber
|
||||
LEFT JOIN
|
||||
arrival_summary a ON l.BillOfLadingNumber = a.HandoverNumber
|
||||
LEFT JOIN
|
||||
arrival_summary b ON l.MasterPackageNumber = b.HandoverNumber
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = :billOfLadingNumber OR :billOfLadingNumber IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = :masterPackageNumber OR :masterPackageNumber IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= :endDate OR :endDate IS NULL)
|
||||
GROUP BY
|
||||
l.MasterPackageNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
## 3. 参数说明
|
||||
|
||||
| 参数 | 类型 | 描述 |
|
||||
|------|------|------|
|
||||
| customerId | INT | 客户ID |
|
||||
| billOfLadingNumber | VARCHAR(100) | 提单号 |
|
||||
| masterPackageNumber | VARCHAR(100) | 大箱号 |
|
||||
| startDate | DATETIME | 开始日期 |
|
||||
| endDate | DATETIME | 结束日期 |
|
||||
|
||||
## 4. 性能优化建议
|
||||
|
||||
1. **索引优化**:
|
||||
- 在 `label_replace_requests` 表上添加以下索引:
|
||||
- `(CustomerId, CreatedAt)`
|
||||
- `(BillOfLadingNumber, CreatedAt)`
|
||||
- `(MasterPackageNumber, CreatedAt)`
|
||||
- 在 `label_scan_history` 表上添加索引:
|
||||
- `(NeutralWaybillNumber, Result)`
|
||||
- 在 `arrival_handover_forms` 表上添加索引:
|
||||
- `(HandoverNumber, ReceiptTime)`
|
||||
|
||||
2. **查询优化**:
|
||||
- 使用 CTE (Common Table Expressions) 减少重复子查询
|
||||
- 避免在 GROUP BY 子句中使用函数
|
||||
- 合理使用 LEFT JOIN 替代子查询
|
||||
|
||||
3. **数据量控制**:
|
||||
- 考虑添加分页功能,避免一次性返回大量数据
|
||||
- 对于历史数据,可以考虑归档策略
|
||||
|
||||
4. **执行计划分析**:
|
||||
- 使用 `EXPLAIN` 分析查询执行计划
|
||||
- 确保索引被正确使用
|
||||
- 优化 JOIN 顺序
|
||||
|
||||
## 5. 注意事项
|
||||
|
||||
- 以上语句假设数据库表结构与当前代码一致
|
||||
- 实际使用时需要替换参数占位符(如 `1`)为实际值
|
||||
- 对于大量数据,建议使用优化版本的查询语句
|
||||
- 可以根据实际情况调整索引策略
|
||||
239
.trae/specs/dashboard_query_sql/mysql_statements_fixed.md
Normal file
239
.trae/specs/dashboard_query_sql/mysql_statements_fixed.md
Normal file
@@ -0,0 +1,239 @@
|
||||
# 数据看板查询 MySQL 语句(修复版)
|
||||
|
||||
## 1. 提单号预报查询
|
||||
|
||||
### 1.1 基本查询语句
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
l.BillOfLadingNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
(SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - (SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplacePendingCount,
|
||||
(SELECT MIN(h.ReceiptTime)
|
||||
FROM arrival_handover_forms h
|
||||
WHERE h.HandoverNumber = l.BillOfLadingNumber
|
||||
OR h.HandoverNumber = l.MasterPackageNumber) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = 'BOL123456' OR 'BOL123456' IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = 'MP123456' OR 'MP123456' IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= '2026-12-31' OR '2026-12-31' IS NULL)
|
||||
GROUP BY
|
||||
l.BillOfLadingNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
### 1.2 优化版本(使用子查询优化扫描记录统计)
|
||||
|
||||
```sql
|
||||
WITH scan_summary AS (
|
||||
SELECT
|
||||
NeutralWaybillNumber,
|
||||
COUNT(*) AS ReturnedLabelCount
|
||||
FROM
|
||||
label_scan_history
|
||||
WHERE
|
||||
Result = 0
|
||||
GROUP BY
|
||||
NeutralWaybillNumber
|
||||
),
|
||||
arrival_summary AS (
|
||||
SELECT
|
||||
HandoverNumber,
|
||||
MIN(ReceiptTime) AS MinReceiptTime
|
||||
FROM
|
||||
arrival_handover_forms
|
||||
GROUP BY
|
||||
HandoverNumber
|
||||
)
|
||||
SELECT
|
||||
l.BillOfLadingNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplacePendingCount,
|
||||
COALESCE(a.MinReceiptTime, b.MinReceiptTime) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
LEFT JOIN
|
||||
scan_summary s ON l.NeutralWaybillNumber = s.NeutralWaybillNumber
|
||||
LEFT JOIN
|
||||
arrival_summary a ON l.BillOfLadingNumber = a.HandoverNumber
|
||||
LEFT JOIN
|
||||
arrival_summary b ON l.MasterPackageNumber = b.HandoverNumber
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = 'BOL123456' OR 'BOL123456' IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = 'MP123456' OR 'MP123456' IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= '2026-12-31' OR '2026-12-31' IS NULL)
|
||||
GROUP BY
|
||||
l.BillOfLadingNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
## 2. 大箱号预报查询
|
||||
|
||||
### 2.1 基本查询语句
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
l.MasterPackageNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
(SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - (SELECT COUNT(*)
|
||||
FROM label_scan_history s
|
||||
WHERE s.NeutralWaybillNumber = l.NeutralWaybillNumber
|
||||
AND s.Result = 0) AS ReplacePendingCount,
|
||||
(SELECT MIN(h.ReceiptTime)
|
||||
FROM arrival_handover_forms h
|
||||
WHERE h.HandoverNumber = l.BillOfLadingNumber
|
||||
OR h.HandoverNumber = l.MasterPackageNumber) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = 'BOL123456' OR 'BOL123456' IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = 'MP123456' OR 'MP123456' IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= '2026-12-31' OR '2026-12-31' IS NULL)
|
||||
GROUP BY
|
||||
l.MasterPackageNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
### 2.2 优化版本(使用子查询优化扫描记录统计)
|
||||
|
||||
```sql
|
||||
WITH scan_summary AS (
|
||||
SELECT
|
||||
NeutralWaybillNumber,
|
||||
COUNT(*) AS ReturnedLabelCount
|
||||
FROM
|
||||
label_scan_history
|
||||
WHERE
|
||||
Result = 0
|
||||
GROUP BY
|
||||
NeutralWaybillNumber
|
||||
),
|
||||
arrival_summary AS (
|
||||
SELECT
|
||||
HandoverNumber,
|
||||
MIN(ReceiptTime) AS MinReceiptTime
|
||||
FROM
|
||||
arrival_handover_forms
|
||||
GROUP BY
|
||||
HandoverNumber
|
||||
)
|
||||
SELECT
|
||||
l.MasterPackageNumber AS `Key`,
|
||||
c.CustomerCode AS CustomerCode,
|
||||
COUNT(*) AS ArrivalOrderCount,
|
||||
SUM(CASE WHEN l.Label IS NULL OR l.Label = '' THEN 1 ELSE 0 END) AS NoLabelDataCount,
|
||||
SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) AS LabeledOrderCount,
|
||||
CONCAT(ROUND((SUM(CASE WHEN l.Label IS NOT NULL AND l.Label != '' THEN 1 ELSE 0 END) / COUNT(*)) * 100, 2), '%') AS LabelRate,
|
||||
COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplaceCompletedCount,
|
||||
COUNT(*) - COALESCE(SUM(s.ReturnedLabelCount), 0) AS ReplacePendingCount,
|
||||
COALESCE(a.MinReceiptTime, b.MinReceiptTime) AS ArrivalTime,
|
||||
l.BillOfLadingNumber,
|
||||
l.MasterPackageNumber
|
||||
FROM
|
||||
label_replace_requests l
|
||||
LEFT JOIN
|
||||
customers c ON l.CustomerId = c.Id
|
||||
LEFT JOIN
|
||||
scan_summary s ON l.NeutralWaybillNumber = s.NeutralWaybillNumber
|
||||
LEFT JOIN
|
||||
arrival_summary a ON l.BillOfLadingNumber = a.HandoverNumber
|
||||
LEFT JOIN
|
||||
arrival_summary b ON l.MasterPackageNumber = b.HandoverNumber
|
||||
WHERE
|
||||
1=1
|
||||
-- 客户ID过滤
|
||||
AND (l.CustomerId = 1 OR 1 IS NULL)
|
||||
-- 提单号过滤
|
||||
AND (l.BillOfLadingNumber = 'BOL123456' OR 'BOL123456' IS NULL)
|
||||
-- 大箱号过滤
|
||||
AND (l.MasterPackageNumber = 'MP123456' OR 'MP123456' IS NULL)
|
||||
-- 日期范围过滤
|
||||
AND (l.CreatedAt >= '2026-01-01' OR '2026-01-01' IS NULL)
|
||||
AND (l.CreatedAt <= '2026-12-31' OR '2026-12-31' IS NULL)
|
||||
GROUP BY
|
||||
l.MasterPackageNumber
|
||||
ORDER BY
|
||||
l.CreatedAt DESC;
|
||||
```
|
||||
|
||||
## 3. 使用说明
|
||||
|
||||
1. **参数说明**:
|
||||
- 客户ID:1(示例值,根据实际情况修改)
|
||||
- 提单号:'BOL123456'(示例值,根据实际情况修改)
|
||||
- 大箱号:'MP123456'(示例值,根据实际情况修改)
|
||||
- 开始日期:'2026-01-01'(示例值,根据实际情况修改)
|
||||
- 结束日期:'2026-12-31'(示例值,根据实际情况修改)
|
||||
|
||||
2. **注意事项**:
|
||||
- `Key` 是 MySQL 关键字,使用反引号包围
|
||||
- 所有字符串参数都使用单引号包围
|
||||
- 日期参数使用 'YYYY-MM-DD' 格式
|
||||
- 可以根据实际需要修改示例值
|
||||
|
||||
3. **性能优化**:
|
||||
- 对于大量数据,建议使用优化版本的查询语句
|
||||
- 确保相关表有合适的索引
|
||||
- 可以使用 `EXPLAIN` 分析查询执行计划
|
||||
67
.trae/specs/dashboard_query_sql/spec.md
Normal file
67
.trae/specs/dashboard_query_sql/spec.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# 数据看板查询逻辑分析 - MySQL语句分析
|
||||
|
||||
## Overview
|
||||
- **Summary**: 分析数据看板查询的MySQL语句实现,包括标签替换请求的获取、过滤、分组和统计逻辑
|
||||
- **Purpose**: 帮助排查数据看板查询逻辑的问题,提供MySQL语句的等价实现
|
||||
- **Target Users**: 开发人员、数据库管理员
|
||||
|
||||
## Goals
|
||||
- 分析数据看板查询的完整流程
|
||||
- 提供MySQL等价语句
|
||||
- 识别潜在的性能问题
|
||||
- 提供优化建议
|
||||
|
||||
## Non-Goals (Out of Scope)
|
||||
- 不修改现有代码
|
||||
- 不涉及前端实现细节
|
||||
- 不处理权限和安全问题
|
||||
|
||||
## Background & Context
|
||||
数据看板通过 `DashboardController.GetDashboardData` 接口获取数据,该接口调用 `LabelReplaceService.GetDashboardDataAsync` 方法。当前实现使用内存过滤和分组,可能在数据量较大时存在性能问题。
|
||||
|
||||
## Functional Requirements
|
||||
- **FR-1**: 支持按提单号或大箱号查询
|
||||
- **FR-2**: 支持按客户ID过滤
|
||||
- **FR-3**: 支持按日期范围过滤
|
||||
- **FR-4**: 计算到货订单数量、无标签数据数量、已有标签率、换单完成数量、未换单完成数量
|
||||
- **FR-5**: 获取到货时间
|
||||
|
||||
## Non-Functional Requirements
|
||||
- **NFR-1**: 性能优化,避免全表扫描
|
||||
- **NFR-2**: 代码可读性和可维护性
|
||||
- **NFR-3**: 数据准确性
|
||||
|
||||
## Constraints
|
||||
- **Technical**: 使用MySQL数据库,SqlSugar ORM框架
|
||||
- **Business**: 无特殊业务约束
|
||||
- **Dependencies**: 依赖 `label_replace_requests`、`label_scan_history`、`arrival_handover_forms` 表
|
||||
|
||||
## Assumptions
|
||||
- 数据库表结构已正确创建
|
||||
- 所有必要的索引已添加
|
||||
- 数据量在合理范围内
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### AC-1: 基本查询功能
|
||||
- **Given**: 提供查询参数(类型、提单号/大箱号、日期范围、客户ID)
|
||||
- **When**: 调用数据看板查询接口
|
||||
- **Then**: 返回正确的统计数据
|
||||
- **Verification**: `programmatic`
|
||||
|
||||
### AC-2: 性能优化
|
||||
- **Given**: 数据量较大(如10万条记录)
|
||||
- **When**: 执行查询
|
||||
- **Then**: 查询响应时间在可接受范围内(<5秒)
|
||||
- **Verification**: `programmatic`
|
||||
|
||||
### AC-3: 数据准确性
|
||||
- **Given**: 存在测试数据
|
||||
- **When**: 执行查询并与手动计算结果比较
|
||||
- **Then**: 统计数据与手动计算一致
|
||||
- **Verification**: `human-judgment`
|
||||
|
||||
## Open Questions
|
||||
- [ ] 到货时间的获取逻辑是否完整?
|
||||
- [ ] 扫描记录的查询是否需要进一步优化?
|
||||
- [ ] 是否需要添加更多索引以提高性能?
|
||||
53
.trae/specs/dashboard_query_sql/tasks.md
Normal file
53
.trae/specs/dashboard_query_sql/tasks.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 数据看板查询逻辑分析 - 实现计划
|
||||
|
||||
## [x] Task 1: 分析当前查询逻辑
|
||||
- **Priority**: P0
|
||||
- **Depends On**: None
|
||||
- **Description**:
|
||||
- 分析 `LabelReplaceService.GetDashboardDataAsync` 方法的实现
|
||||
- 了解当前的过滤、分组和统计逻辑
|
||||
- 识别潜在的性能问题
|
||||
- **Acceptance Criteria Addressed**: AC-1, AC-3
|
||||
- **Test Requirements**:
|
||||
- `human-judgment` TR-1.1: 理解当前代码逻辑
|
||||
- `human-judgment` TR-1.2: 识别性能瓶颈
|
||||
- **Notes**: 重点关注内存过滤和分组的性能影响
|
||||
|
||||
## [x] Task 2: 生成 MySQL 等价语句
|
||||
- **Priority**: P0
|
||||
- **Depends On**: Task 1
|
||||
- **Description**:
|
||||
- 为提单号预报生成 MySQL 等价语句
|
||||
- 为大箱号预报生成 MySQL 等价语句
|
||||
- 包含所有过滤条件和统计计算
|
||||
- **Acceptance Criteria Addressed**: AC-1, AC-3
|
||||
- **Test Requirements**:
|
||||
- `programmatic` TR-2.1: 验证 MySQL 语句的正确性
|
||||
- `human-judgment` TR-2.2: 确保语句可读性
|
||||
- **Notes**: 使用 MySQL 聚合函数和分组操作
|
||||
|
||||
## [x] Task 3: 性能优化分析
|
||||
- **Priority**: P1
|
||||
- **Depends On**: Task 2
|
||||
- **Description**:
|
||||
- 分析 MySQL 语句的性能
|
||||
- 识别可能的优化点
|
||||
- 提供索引建议
|
||||
- **Acceptance Criteria Addressed**: AC-2
|
||||
- **Test Requirements**:
|
||||
- `human-judgment` TR-3.1: 分析查询执行计划
|
||||
- `human-judgment` TR-3.2: 评估索引使用情况
|
||||
- **Notes**: 考虑使用 EXPLAIN 分析查询执行计划
|
||||
|
||||
## [x] Task 4: 编写完整的 MySQL 语句文档
|
||||
- **Priority**: P1
|
||||
- **Depends On**: Task 2, Task 3
|
||||
- **Description**:
|
||||
- 编写详细的 MySQL 语句文档
|
||||
- 包含参数说明和使用示例
|
||||
- 提供性能优化建议
|
||||
- **Acceptance Criteria Addressed**: AC-1, AC-2, AC-3
|
||||
- **Test Requirements**:
|
||||
- `human-judgment` TR-4.1: 文档完整性
|
||||
- `human-judgment` TR-4.2: 文档可读性
|
||||
- **Notes**: 确保文档包含所有必要的信息
|
||||
Reference in New Issue
Block a user