Files
JY1.0/生产计划SQL开发文档.md
2026-05-21 09:46:02 +08:00

244 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# **车间生产管理SQL开发 - 逐步构建生产计划视图与存储过程**
## **1. 原始需求与基础查询**
**目标**:从多个关联表中查询生产数据,并逐步添加计算字段。
### **1.1 基础数据源**
涉及三张核心表和视图:
- `车间生产管理_零件工序_视图`:包含订单号、产品名称、零件名称、工序、数量等。
- `车间生产管理工艺_零件工序_任务分配`:包含工序流水号、计划数量、加工数量、计划日期等。
- `基础数据_设备工位点检表`:包含设备流水号、工位号、设备名称。
### **1.2 初始联接查询**
通过 `工序流水号` 和 `设备流水号` 联接上述三张表。
sql
```
SELECT dbo.车间生产管理_零件工序_视图.订单号,
dbo.车间生产管理_零件工序_视图.产品名称,
-- ... 其他字段
dbo.基础数据_设备工位点检表.工位号 + N':' + dbo.基础数据_设备工位点检表.设备名称 AS 设备,
dbo.车间生产管理_零件工序_视图.数量 AS 订单数,
dbo.车间生产管理工艺_零件工序_任务分配.数量 AS 计划数
-- ... 其他字段
FROM dbo.车间生产管理工艺_零件工序_任务分配
INNER JOIN dbo.车间生产管理_零件工序_视图 ON dbo.车间生产管理工艺_零件工序_任务分配.工序流水号 = dbo.车间生产管理_零件工序_视图.工序流水号
INNER JOIN dbo.基础数据_设备工位点检表 ON dbo.车间生产管理工艺_零件工序_任务分配.设备流水号 = dbo.基础数据_设备工位点检表.设备流水号
```
## **2. 逐步新增计算字段**
在基础查询上,根据业务需求分步添加了三个计算字段。
### **2.1 新增 `状态` 字段**
**需求**:根据加工数量与计划数量的对比,判断订单状态为“派工中”、“生产中”或“已完成”。
**逻辑**
- **已完成**:加工数量 >= 计划数量
- **生产中**0 < 加工数量 < 计划数量
- **派工中**:加工数量 = 0 或 NULL
**SQL 片段**
sql
```
CASE
WHEN ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) >= dbo.车间生产管理工艺_零件工序_任务分配.数量
THEN '已完成'
WHEN ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) > 0
AND ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) < dbo.车间生产管理工艺_零件工序_任务分配.数量
THEN '生产中'
ELSE '派工中'
END AS 状态
```
### **2.2 新增 `完成率` 字段**
**需求**:计算完成率 = (加工数量 / 计划数量) × 100%。
**SQL 片段**
sql
```
CASE
WHEN ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.数量, 0) = 0 THEN '0%'
ELSE CAST(ROUND(ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) * 100.0 /
dbo.车间生产管理工艺_零件工序_任务分配.数量, 2) AS DECIMAL(10, 2)) + '%'
END AS 完成率
```
### **2.3 新增 `投产时间` 字段**
**需求**:从 `车间生产管理工艺_零件工艺计划` 表获取 `分配日期`,作为投产时间。
**实现**:需要 `LEFT JOIN` 新表,通过 `工艺计划流水号` 关联。
sql
```
-- 新增的 JOIN
LEFT OUTER JOIN dbo.车间生产管理工艺_零件工艺计划
ON dbo.车间生产管理_零件工序_视图.工艺计划流水号 = dbo.车间生产管理工艺_零件工艺计划.工艺计划流水号
-- 新增字段
CONVERT(varchar(10), dbo.车间生产管理工艺_零件工艺计划.分配日期, 23) AS 投产时间
```
## **3. 创建生产计划视图 (`车间生产管理_生产计划_视图_新`)**
将上述所有逻辑整合,创建了一个名为 `车间生产管理_生产计划_视图_新` 的视图。
sql
```
CREATE VIEW dbo.车间生产管理_生产计划_视图_新 AS
SELECT dbo.车间生产管理_零件工序_视图.订单号,
dbo.车间生产管理_零件工序_视图.产品名称,
dbo.车间生产管理_零件工序_视图.零件名称,
dbo.车间生产管理_零件工序_视图.工序,
dbo.基础数据_设备工位点检表.工位号 + N':' + dbo.基础数据_设备工位点检表.设备名称 AS 设备,
dbo.车间生产管理_零件工序_视图.数量 AS 订单数,
dbo.车间生产管理工艺_零件工序_任务分配.数量 AS 计划数,
CONVERT(varchar(10), dbo.车间生产管理工艺_零件工序_任务分配.计划完成日期, 23) AS 计划完成日期,
dbo.车间生产管理工艺_零件工序_任务分配.数量 - dbo.车间生产管理工艺_零件工序_任务分配.加工数量 AS 剩余数,
dbo.车间生产管理_零件工序_视图.零件图号,
dbo.车间生产管理_零件工序_视图.工序顺序,
CONVERT(varchar(10), dbo.车间生产管理工艺_零件工序_任务分配.计划开始日期, 23) AS 计划开始日期,
dbo.基础数据_设备工位点检表.设备名称,
-- 状态字段
CASE
WHEN ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) >= dbo.车间生产管理工艺_零件工序_任务分配.数量
THEN '已完成'
WHEN ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) > 0
AND ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) < dbo.车间生产管理工艺_零件工序_任务分配.数量
THEN '生产中'
ELSE '派工中'
END AS 状态,
-- 完成率字段
CASE
WHEN ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.数量, 0) = 0 THEN '0%'
ELSE CAST(ROUND(ISNULL(dbo.车间生产管理工艺_零件工序_任务分配.加工数量, 0) * 100.0 /
dbo.车间生产管理工艺_零件工序_任务分配.数量, 2) AS DECIMAL(10, 2)) + '%'
END AS 完成率,
CONVERT(varchar(10), dbo.车间生产管理工艺_零件工艺计划.分配日期, 23) AS 投产时间,
dbo.车间生产管理_零件工序_视图.精工期限
FROM dbo.车间生产管理工艺_零件工序_任务分配
INNER JOIN dbo.车间生产管理_零件工序_视图
ON dbo.车间生产管理工艺_零件工序_任务分配.工序流水号 = dbo.车间生产管理_零件工序_视图.工序流水号
INNER JOIN dbo.基础数据_设备工位点检表
ON dbo.车间生产管理工艺_零件工序_任务分配.设备流水号 = dbo.基础数据_设备工位点检表.设备流水号
LEFT OUTER JOIN dbo.车间生产管理工艺_零件工艺计划
ON dbo.车间生产管理_零件工序_视图.工艺计划流水号 = dbo.车间生产管理工艺_零件工艺计划.工艺计划流水号
```
### **4. 视图创建后的关键Bug与修复**
#### **4.1 Bug #1查询视图时“varchar转换为numeric”错误**
**原因**:在计算`完成率`字段时错误地将数字DECIMAL与字符串'%'直接拼接SQL Server无法自动处理类型转换。\
**修复**将计算得到的数字显式转换为字符串VARCHAR后再拼接。
sql
```
-- 错误写法
CAST(... AS DECIMAL(10, 2)) + '%'
-- 正确写法
CAST(CAST(... AS DECIMAL(10, 2)) AS VARCHAR(20)) + '%'
```
#### **4.2 Bug #2存储过程中“列名年份无效”和“modulo运算符不兼容”**
**原因**
1. 最初假设视图包含`年份``月份`字段,但实际视图不包含,导致筛选失败。
2. 动态SQL中拼接`LIKE`子句时单引号处理混乱导致SQL Server将部分字符串和`%`误解析为模运算。
**最终修复**
1. **利用已有字段筛选**:使用视图中的`投产时间`字段进行模糊匹配。
sql
```
-- 动态SQL中的WHERE部分
WHERE (投产时间 like @月份 + '-%' or 计划完成日期 like @月份 + '-%')
```
2. **正确拼接动态SQL**:确保参数化查询,避免字符串拼接错误。
sql
```
-- 存储过程中正确的拼接和参数传递示例
ALTER PROCEDURE [dbo].[车间生产管理_生产计划_查询数据]
@月份 nvarchar(50),
@零件名称_check bit = null,
@零件名称 nvarchar(50) = null,
@状态_check bit = null,
@状态 nvarchar(50) = null
AS
BEGIN
DECLARE @selectStr NVARCHAR(4000) = 'SELECT * FROM 车间生产管理_生产计划_视图_新 WHERE (投产时间 like @月份 + ''-%'' or 计划完成日期 like @月份 + ''-%'')';
IF @零件名称_check = 1
SET @selectStr = @selectStr + ' AND 零件名称 like ''%'' + @零件名称 + ''%''';
IF @状态_check = 1
SET @selectStr = @selectStr + ' AND 状态 = @状态';
EXEC sp_executesql @selectStr,
N'@月份 nvarchar(50), @零件名称 nvarchar(50), @状态 nvarchar(50)',
@月份, @零件_name, @状态;
END
```
### **5. 新增 `` 和 `` 字段**
为方便按年月筛选,在最终视图中从`投产时间`(分配日期)中直接提取``和``两个独立字段。
**最终视图SQL含年、月字段**
sql
```
SELECT -- ... 其他字段 ...
CASE WHEN dbo.车间生产管理工艺_零件工艺计划.分配日期 IS NOT NULL
THEN YEAR(dbo.车间生产管理工艺_零件工艺计划.分配日期)
ELSE NULL END AS 年,
CASE WHEN dbo.车间生产管理工艺_零件工艺计划.分配日期 IS NOT NULL
THEN MONTH(dbo.车间生产管理工艺_零件工艺计划.分配日期)
ELSE NULL END AS 月
FROM -- ... 表联接 ...
```
这样存储过程可直接使用`WHERE 年 = @年 AND 月 = @月`进行筛选,更为高效。
### **6. 最终调用示例**
在应用程序中调用存储过程,传入参数。
json
```
{
"合同编号": "",
"合同编号_check": 0,
"零件名称_check": 0,
"零件名称": "",
"产品名称_check": 0,
"产品名称": "",
"状态_check": 0,
"状态": "",
"月份": "2025-04"
}
```