9.9 KiB
9.9 KiB
车间生产管理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运算符不兼容”
原因:
- 最初假设视图包含
年份和月份字段,但实际视图不包含,导致筛选失败。 - 动态SQL中拼接
LIKE子句时,单引号处理混乱,导致SQL Server将部分字符串和%误解析为模运算。
最终修复:
-
利用已有字段筛选:使用视图中的
投产时间字段进行模糊匹配。sql
-- 动态SQL中的WHERE部分 WHERE (投产时间 like @月份 + '-%' or 计划完成日期 like @月份 + '-%') -
正确拼接动态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"
}