From 968c1ccb7a91246c1a846e7d7efd12bbe7cc7ab8 Mon Sep 17 00:00:00 2001 From: geh <1923421292@qq.com> Date: Fri, 5 Dec 2025 14:37:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E6=96=BD=E5=B7=A5=E4=BA=BA=E5=8A=9B?= =?UTF-8?q?=E9=A2=84=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SGGL/BLL/JDGL/SGManPower/SGManPowerService.cs | 532 ++++++------------ .../JDGL/SGManPower/SGWarningDetailsEdit.aspx | 5 +- .../SGManPower/SGWarningDetailsEdit.aspx.cs | 35 +- 3 files changed, 205 insertions(+), 367 deletions(-) diff --git a/SGGL/BLL/JDGL/SGManPower/SGManPowerService.cs b/SGGL/BLL/JDGL/SGManPower/SGManPowerService.cs index 57e1f90b..d5242221 100644 --- a/SGGL/BLL/JDGL/SGManPower/SGManPowerService.cs +++ b/SGGL/BLL/JDGL/SGManPower/SGManPowerService.cs @@ -21,7 +21,6 @@ namespace BLL foreach (var project in projects) { // 检查管理人员到期未到岗情况 - // var items1 = CheckManagerNotArrived(project.ProjectId); var items1 = CheckHistoricalContinuousShortage(project.ProjectId); // 检查作业人员人力偏差情况 @@ -49,114 +48,101 @@ namespace BLL } - /*/// - /// 检查管理人员到期未到岗情况(超过一周发出预警) + #region 检查所有历史数据中连续一周以上人力不足的情况 + + /// + /// 检查所有历史数据中连续一周以上人力不足的情况 /// - /// 项目ID - private static IEnumerable CheckManagerNotArrived(string projectId) + private static IEnumerable CheckHistoricalContinuousShortage(string projectId) { - //获取计划的最新版本 - var version = "1"; - var sgMan = Funs.DB.JDGL_SGManPower.Where(x => x.ProjectId == projectId).OrderByDescending(x => x.Version) - .FirstOrDefault(); - if (sgMan != null) - { - version = sgMan.Version; - } - - // 先获取计划表超过一周的管理岗位有哪些 - var dataList = (from x in Funs.DB.JDGL_SGManPower - join p in Funs.DB.Base_WorkPost on x.WorkPostId equals p.WorkPostId into pp - from y in pp.DefaultIfEmpty() - where x.ProjectId == projectId && (y.PostType == "4" || y.PostType == "1") && - x.PlanDate <= DateTime.Now.AddDays(-7) && x.Version == version - select x).ToList(); - - var lItems = new List(); - //循环检查实际考勤中的人数 - foreach (var data in dataList) - { - //根据人员计划表获取计划中的管理人员数 - int num = getInOutRecordNum(data); - if (data.Quantity > num) - { - lItems = SendManagerWarning(data.UnitId, projectId, data.WorkPostId, data.UnitWorkId, data.PlanDate, - data.Quantity, num); - } - } - - return lItems; - }*/ - - /*//获取实际考勤人员数 - private static int getInOutRecordNum(JDGL_SGManPower sgManPower) - { - string strSql = @" - SELECT e.UnitId, e.PostId, e.RecordDate, p.WorkAreaId as UnitWorkId - FROM T_d_EmployInOutRecord e INNER JOIN SitePerson_Person p ON e.IDCardNo = p.IdentityCard AND e.ProjectId = p.ProjectId - WHERE e.PostId IS NOT NULL AND e.PostId != '' - AND e.ProjectId = @ProjectId - AND e.RecordDate = @RecordDate - AND e.UnitId = @UnitId - AND e.PostId = @PostId"; + string strSql = @"WITH LatestVersions AS ( + SELECT ProjectId, MAX(Version) AS MaxVersion + FROM JDGL_SGManPower + WHERE ProjectId = @ProjectId + GROUP BY ProjectId + ), + PlanVsActual AS ( + SELECT + p.ProjectId, + p.UnitId, + p.UnitWorkId, + p.WorkPostId, + p.PlanDate, + p.Quantity AS PlanQuantity, + ISNULL(a.num, 0) AS num, + CASE WHEN ISNULL(a.num, 0) < p.Quantity THEN 1 ELSE 0 END AS IsShortage, + lv.MaxVersion + FROM JDGL_SGManPower p + INNER JOIN LatestVersions lv ON p.ProjectId = lv.ProjectId AND p.Version = lv.MaxVersion + LEFT JOIN ( SELECT ProjectId,UnitId,WorkPostId,IntoOutTime,WorkAreaId,num FROM SitePerson_Checking_Statistics ) a ON p.ProjectId = a.ProjectId + AND p.UnitId = a.UnitId + AND p.WorkPostId = a.WorkPostId + AND p.PlanDate = a.IntoOutTime + AND (CHARINDEX(',' + p.UnitWorkId + ',', ',' + ISNULL(a.WorkAreaId, '') + ',') > 0 + OR (ISNULL(a.WorkAreaId, '') = '' AND ISNULL(p.UnitWorkId, '') = '')) + WHERE p.ProjectId = @ProjectId AND p.PlanDate <= GETDATE() + ), + ShortageWithRowNum AS ( + SELECT *, + ROW_NUMBER() OVER ( + PARTITION BY ProjectId, UnitId, UnitWorkId, WorkPostId + ORDER BY PlanDate + ) AS RowNum + FROM PlanVsActual + WHERE IsShortage = 1 + ), + ContinuousGroups AS ( + SELECT *, + DATEADD(DAY, -RowNum, PlanDate) AS GroupId + FROM ShortageWithRowNum + ), + ContinuousCounts AS ( + SELECT + ProjectId, + UnitId, + UnitWorkId, + WorkPostId, + GroupId, + COUNT(*) AS ContinuousDays, + MIN(PlanDate) AS StartDate, + MAX(PlanDate) AS EndDate, + SUM(PlanQuantity) as PlanQuantity, + SUM(num) as num, + MaxVersion + FROM ContinuousGroups + GROUP BY ProjectId, UnitId, UnitWorkId, WorkPostId, GroupId,MaxVersion + ) + SELECT + ProjectId, + UnitId, + UnitWorkId, + WorkPostId, + ContinuousDays, + MaxVersion, + StartDate, + EndDate,PlanQuantity,num + FROM ContinuousCounts + WHERE ContinuousDays >= 7"; var parameters = new List { - new System.Data.SqlClient.SqlParameter("@ProjectId", sgManPower.ProjectId), - new System.Data.SqlClient.SqlParameter("@RecordDate", sgManPower.PlanDate), - new System.Data.SqlClient.SqlParameter("@UnitId", sgManPower.UnitId), - new System.Data.SqlClient.SqlParameter("@PostId", sgManPower.WorkPostId), + new System.Data.SqlClient.SqlParameter("@ProjectId", projectId) }; - - // 执行查询获取分组数据 + var warningItems = new List(); var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray()); - // 创建一个新的DataTable来存储处理后的数据 - DataTable processedDt = dt.Clone(); - foreach (System.Data.DataRow row in dt.Rows) + foreach (DataRow row in dt.Rows) { - string ids = row["UnitWorkId"] != DBNull.Value ? row["UnitWorkId"].ToString() : string.Empty; - if (!string.IsNullOrEmpty(ids)) - { - string[] unitWorkIdArray = ids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string unitWorkId in unitWorkIdArray) - { - // 往processedDt里面添加数据,每个UnitWorkId一行 - DataRow newRow = processedDt.NewRow(); - newRow["UnitId"] = row["UnitId"]; - newRow["PostId"] = row["PostId"]; - newRow["RecordDate"] = row["RecordDate"]; - newRow["UnitWorkId"] = unitWorkId.Trim(); - processedDt.Rows.Add(newRow); - } - } - else - { - DataRow newRow = processedDt.NewRow(); - newRow["UnitId"] = row["UnitId"]; - newRow["PostId"] = row["PostId"]; - newRow["RecordDate"] = row["RecordDate"]; - newRow["UnitWorkId"] = string.Empty; - processedDt.Rows.Add(newRow); - } + warningItems.AddRange(SendManagerWarning(row["UnitId"].ToString(), row["ProjectId"].ToString(), + row["WorkPostId"].ToString(), row["UnitWorkId"].ToString(), + Convert.ToDateTime(row["StartDate"]), Convert.ToDateTime(row["EndDate"]), + Convert.ToInt32(row["PlanQuantity"]), Convert.ToInt32(row["num"]))); } - // 确定要用于后续处理的数据源 - IEnumerable dataSource = processedDt.AsEnumerable(); + return warningItems; + } - if (string.IsNullOrEmpty(sgManPower.UnitWorkId)) - { - dataSource = dataSource.Where(x => x["UnitWorkId"] == null); - } - else - { - dataSource = dataSource.Where(x => - x["UnitWorkId"] != DBNull.Value && x["UnitWorkId"].ToString() == sgManPower.UnitWorkId); - } - - return dataSource.Count(); - }*/ /// /// 发送管理人员预警 @@ -283,30 +269,13 @@ namespace BLL { urlParams += "&startTime=" + string.Format("{0:yyyy-MM-dd}", startDate); } - + // 添加时间参数 if (endDate.HasValue) { urlParams += "&endTime=" + string.Format("{0:yyyy-MM-dd}", endDate); } - // // 添加岗位参数(如果已选择) - // if (quantity.HasValue) - // { - // urlParams += "&quantity=" + quantity.Value; - // } - // - // // 添加岗位参数(如果已选择) - // if (num >= 0) - // { - // urlParams += "&num=" + num; - // } - // else - // { - // urlParams += "&num=0"; - // } - - foreach (var userId in toUserIds) { Model.ToDoItem toDoItem = new Model.ToDoItem(); @@ -327,143 +296,120 @@ namespace BLL return toDoItems; } + #endregion + + + #region 检查作业人员人力偏差情况 + // /// - // /// 检查作业人员人力偏差情况(一周内累计偏差值超过计划的10%) + // /// 检查作业人员人力偏差情况(一周内(连续7天不是最近七天)累计偏差值超过计划的10%) // /// // /// 项目ID private static IEnumerable CheckWorkerDeviation(string projectId) { - //获取计划的最新版本 - var version = "1"; - var sgMan = Funs.DB.JDGL_SGManPower.Where(x => x.ProjectId == projectId).OrderByDescending(x => x.Version) - .FirstOrDefault(); - if (sgMan != null) - { - version = sgMan.Version; - } - - //当前时间 - var endDate = DateTime.Now; - //当前时间前7天 - var startDate = DateTime.Now.AddDays(-7); - // 先获取计划表一周的作业岗位有哪些 - var dataList = (from x in Funs.DB.JDGL_SGManPower - join p in Funs.DB.Base_WorkPost on x.WorkPostId equals p.WorkPostId into pp - from y in pp.DefaultIfEmpty() - where x.ProjectId == projectId && (y.PostType == "2" || y.PostType == "3") && - x.PlanDate >= startDate && x.PlanDate <= endDate && x.Version == version - group x by new - { - x.UnitId, - x.UnitWorkId, - x.WorkPostId - } - into g - select new - { - UnitId = g.Key.UnitId, - UnitWorkId = g.Key.UnitWorkId, - WorkPostId = g.Key.WorkPostId, - QuantitySum = g.Sum(x => x.Quantity) - }).ToList(); - - var lItems = new List(); - //循环检查实际考勤中的人数 - foreach (var data in dataList) - { - //根据人员计划表获取计划中的作业人员数 - int num = getInOutRecordNum1(data.UnitId, data.UnitWorkId, data.WorkPostId, projectId); - - // 计算偏差百分比 - if (data.QuantitySum != 0) - { - double deviationPercentage = Math.Abs((double)((data.QuantitySum - num) / data.QuantitySum)); - // 如果偏差超过10%,发出预警 - if (deviationPercentage > 0.1) - { - lItems = SendWorkerDeviationWarning(data.UnitId, projectId, data.WorkPostId, data.UnitWorkId, - startDate, endDate, data.QuantitySum, num); - } - } - } - - return lItems; - } - - - //获取实际考勤人员数 - private static int getInOutRecordNum1(string unitId, string unitWorkId, string workPostId, string projectId) - { - string strSql = @" - SELECT e.UnitId, e.PostId, e.RecordDate, p.WorkAreaId as UnitWorkId - FROM T_d_EmployInOutRecord e INNER JOIN SitePerson_Person p ON e.IDCardNo = p.IdentityCard AND e.ProjectId = p.ProjectId - WHERE e.PostId IS NOT NULL AND e.PostId != '' - AND e.ProjectId = @ProjectId - AND e.UnitId = @UnitId - AND e.PostId = @PostId - AND e.RecordDate >= @StartDate - AND e.RecordDate <= @EndDate"; + string strSql = @"WITH LatestVersions AS ( + SELECT ProjectId, MAX(Version) AS MaxVersion + FROM JDGL_SGManPower + WHERE ProjectId = @ProjectId + GROUP BY ProjectId + ), + PlanVsActual AS ( + SELECT + p.ProjectId, + p.UnitId, + p.UnitWorkId, + p.WorkPostId, + p.PlanDate, + p.Quantity AS PlanQuantity, + ISNULL(a.num, 0) AS num, + CASE + WHEN p.Quantity > 0 AND ABS(CAST((p.Quantity - ISNULL(a.num, 0)) AS FLOAT) / p.Quantity) > 0.1 + THEN 1 + ELSE 0 + END AS HasDeviation, + lv.MaxVersion + FROM JDGL_SGManPower p + INNER JOIN LatestVersions lv ON p.ProjectId = lv.ProjectId AND p.Version = lv.MaxVersion + LEFT JOIN ( + SELECT ProjectId,UnitId,WorkPostId,IntoOutTime,WorkAreaId,num + FROM SitePerson_Checking_Statistics + ) a ON p.ProjectId = a.ProjectId + AND p.UnitId = a.UnitId + AND p.WorkPostId = a.WorkPostId + AND p.PlanDate = a.IntoOutTime + AND (CHARINDEX(',' + p.UnitWorkId + ',', ',' + ISNULL(a.WorkAreaId, '') + ',') > 0 + OR (ISNULL(a.WorkAreaId, '') = '' AND ISNULL(p.UnitWorkId, '') = '')) + WHERE p.ProjectId = @ProjectId AND p.PlanDate <= GETDATE() + ), + DeviationWithRowNum AS ( + SELECT *, + ROW_NUMBER() OVER ( + PARTITION BY ProjectId, UnitId, UnitWorkId, WorkPostId + ORDER BY PlanDate + ) AS RowNum + FROM PlanVsActual + WHERE HasDeviation = 1 + ), + ContinuousGroups AS ( + SELECT *, + DATEADD(DAY, -RowNum, PlanDate) AS GroupId + FROM DeviationWithRowNum + ), + ContinuousCounts AS ( + SELECT + ProjectId, + UnitId, + UnitWorkId, + WorkPostId, + GroupId, + COUNT(*) AS ContinuousDays, + MIN(PlanDate) AS StartDate, + MAX(PlanDate) AS EndDate, + SUM(PlanQuantity) as TotalPlanQuantity, + SUM(num) as num, + MaxVersion + FROM ContinuousGroups + GROUP BY ProjectId, UnitId, UnitWorkId, WorkPostId, GroupId, MaxVersion + ) + SELECT + ProjectId, + UnitId, + UnitWorkId, + WorkPostId, + ContinuousDays, + MaxVersion, + StartDate, + EndDate, + TotalPlanQuantity, + num + FROM ContinuousCounts + WHERE ContinuousDays >= 7"; var parameters = new List { - new System.Data.SqlClient.SqlParameter("@ProjectId", projectId), - new System.Data.SqlClient.SqlParameter("@UnitId", unitId), - new System.Data.SqlClient.SqlParameter("@PostId", workPostId), - new System.Data.SqlClient.SqlParameter("@StartDate", DateTime.Now.AddDays(-7)), - new System.Data.SqlClient.SqlParameter("@EndDate", DateTime.Now), + new System.Data.SqlClient.SqlParameter("@ProjectId", projectId) }; - // 执行查询获取分组数据 + var warningItems = new List(); var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray()); - // 创建一个新的DataTable来存储处理后的数据 - DataTable processedDt = dt.Clone(); - - foreach (System.Data.DataRow row in dt.Rows) + foreach (DataRow row in dt.Rows) { - string ids = row["UnitWorkId"] != DBNull.Value ? row["UnitWorkId"].ToString() : string.Empty; - if (!string.IsNullOrEmpty(ids)) - { - string[] unitWorkIdArray = ids.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string id in unitWorkIdArray) - { - // 往processedDt里面添加数据,每个UnitWorkId一行 - DataRow newRow = processedDt.NewRow(); - newRow["UnitId"] = row["UnitId"]; - newRow["PostId"] = row["PostId"]; - newRow["RecordDate"] = row["RecordDate"]; - newRow["UnitWorkId"] = id.Trim(); - processedDt.Rows.Add(newRow); - } - } - else - { - DataRow newRow = processedDt.NewRow(); - newRow["UnitId"] = row["UnitId"]; - newRow["PostId"] = row["PostId"]; - newRow["RecordDate"] = row["RecordDate"]; - newRow["UnitWorkId"] = string.Empty; - processedDt.Rows.Add(newRow); - } + warningItems.AddRange(SendWorkerDeviationWarning( + row["UnitId"].ToString(), + row["ProjectId"].ToString(), + row["WorkPostId"].ToString(), + row["UnitWorkId"].ToString(), + Convert.ToDateTime(row["StartDate"]), + Convert.ToDateTime(row["EndDate"]), + Convert.ToInt32(row["TotalPlanQuantity"]), + Convert.ToInt32(row["num"]) + )); } - // 确定要用于后续处理的数据源 - IEnumerable dataSource = processedDt.AsEnumerable(); - - if (string.IsNullOrEmpty(unitWorkId)) - { - dataSource = dataSource.Where(x => x["UnitWorkId"] == null); - } - else - { - dataSource = dataSource.Where(x => - x["UnitWorkId"] != DBNull.Value && x["UnitWorkId"].ToString() == unitWorkId); - } - - return dataSource.Count(); + return warningItems; } - - + /// /// 发送作业人员偏差预警 /// @@ -473,8 +419,7 @@ namespace BLL /// 实际总人数 /// 偏差百分比 private static List SendWorkerDeviationWarning(string unitId, string projectId, string workPostId, - string unitWorkId, - DateTime? startDate, DateTime? endDate, int? quantity, int num) + string unitWorkId, DateTime? startDate, DateTime? endDate, int? quantity, int num) { // 发送预警信息 var toDoItems = new List(); @@ -560,23 +505,6 @@ namespace BLL string.Format("{0:yyyy-MM-dd}", endDate); } - - // 添加岗位参数(如果已选择) - if (quantity.HasValue) - { - urlParams += "&quantity=" + quantity.Value; - } - - // 添加岗位参数(如果已选择) - if (num >= 0) - { - urlParams += "&num=" + num; - } - else - { - urlParams += "&num=0"; - } - // 发送预警信息 foreach (var userId in toUserIds) { @@ -597,100 +525,6 @@ namespace BLL return toDoItems; } - - /// - /// 检查所有历史数据中连续一周以上人力不足的情况 - /// - private static IEnumerable CheckHistoricalContinuousShortage(string projectId) - { - string strSql = @" -WITH LatestVersions AS ( - SELECT ProjectId, MAX(Version) AS MaxVersion - FROM JDGL_SGManPower - WHERE ProjectId = @ProjectId - GROUP BY ProjectId -), -PlanVsActual AS ( - SELECT - p.ProjectId, - p.UnitId, - p.UnitWorkId, - p.WorkPostId, - p.PlanDate, - p.Quantity AS PlanQuantity, - ISNULL(a.ActualQuantity, 0) AS ActualQuantity, - CASE WHEN ISNULL(a.ActualQuantity, 0) < p.Quantity THEN 1 ELSE 0 END AS IsShortage, - lv.MaxVersion - FROM JDGL_SGManPower p - INNER JOIN LatestVersions lv ON p.ProjectId = lv.ProjectId AND p.Version = lv.MaxVersion - LEFT JOIN ( - SELECT - * FROM View_EmployInOutRecord - ) a ON p.ProjectId = a.ProjectId - AND p.UnitId = a.UnitId - AND p.WorkPostId = a.PostId - AND p.PlanDate = a.RecordDate - AND ISNULL(p.UnitWorkId, '') = ISNULL(a.UnitWorkId, '') - WHERE p.ProjectId = @ProjectId AND p.PlanDate <= GETDATE() -), -ShortageWithRowNum AS ( - SELECT *, - ROW_NUMBER() OVER ( - PARTITION BY ProjectId, UnitId, UnitWorkId, WorkPostId - ORDER BY PlanDate - ) AS RowNum - FROM PlanVsActual - WHERE IsShortage = 1 -), -ContinuousGroups AS ( - SELECT *, - DATEADD(DAY, -RowNum, PlanDate) AS GroupId - FROM ShortageWithRowNum -), -ContinuousCounts AS ( - SELECT - ProjectId, - UnitId, - UnitWorkId, - WorkPostId, - GroupId, - COUNT(*) AS ContinuousDays, - MIN(PlanDate) AS StartDate, - MAX(PlanDate) AS EndDate, - SUM(PlanQuantity) as PlanQuantity, - SUM(ActualQuantity) as ActualQuantity, - MaxVersion - FROM ContinuousGroups - GROUP BY ProjectId, UnitId, UnitWorkId, WorkPostId, GroupId,MaxVersion -) -SELECT - ProjectId, - UnitId, - UnitWorkId, - WorkPostId, - ContinuousDays, - MaxVersion, - StartDate, - EndDate,PlanQuantity,ActualQuantity -FROM ContinuousCounts -WHERE ContinuousDays >= 7"; - - var parameters = new List - { - new System.Data.SqlClient.SqlParameter("@ProjectId", projectId) - }; - var warningItems = new List(); - var dt = SQLHelper.GetDataTableRunText(strSql, parameters.ToArray()); - - - foreach (DataRow row in dt.Rows) - { - warningItems.AddRange(SendManagerWarning(row["UnitId"].ToString(),row["ProjectId"].ToString(),row["WorkPostId"].ToString(),row["UnitWorkId"].ToString(), - Convert.ToDateTime(row["StartDate"]), Convert.ToDateTime(row["EndDate"]), Convert.ToInt32(row["PlanQuantity"]), Convert.ToInt32(row["ActualQuantity"]))); - } - return warningItems; - } - - + #endregion } } \ No newline at end of file diff --git a/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx b/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx index f351703c..084bf104 100644 --- a/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx +++ b/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx @@ -63,9 +63,12 @@ - + + diff --git a/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx.cs b/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx.cs index 75975fca..28db7cdb 100644 --- a/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx.cs +++ b/SGGL/FineUIPro.Web/JDGL/SGManPower/SGWarningDetailsEdit.aspx.cs @@ -127,23 +127,24 @@ namespace FineUIPro.Web.JDGL.SGManPower { string strSql = @"SELECT - p.Id, - p.ProjectId, - p.UnitId, - p.UnitWorkId, - p.WorkPostId, - p.Version, - p.Quantity, - p.PlanDate, - ISNULL(a.ActualQuantity, 0) AS ActualQuantity -FROM JDGL_SGManPower p -LEFT JOIN ( - SELECT * from View_EmployInOutRecord -) a ON p.ProjectId = a.ProjectId - AND p.UnitId = a.UnitId - AND p.WorkPostId = a.PostId - AND p.PlanDate = a.RecordDate - AND ISNULL(p.UnitWorkId, '') = ISNULL(a.UnitWorkId, '') where p.Version = '" + Version + "'"; + p.Id, + p.ProjectId, + p.UnitId, + p.UnitWorkId, + p.WorkPostId, + p.Version, + p.Quantity, + p.PlanDate, + ISNULL(a.num, 0) AS num, + (CASE WHEN p.Quantity > 0 AND ABS(CAST((p.Quantity - ISNULL(a.num, 0)) AS FLOAT) / p.Quantity) > 0.1 + THEN ABS(CAST((p.Quantity - ISNULL(a.num, 0)) AS FLOAT) / p.Quantity) + ELSE 0 end ) as Bias + FROM JDGL_SGManPower p + LEFT JOIN ( SELECT ProjectId,UnitId,WorkPostId,IntoOutTime,WorkAreaId,num FROM SitePerson_Checking_Statistics ) a ON p.ProjectId = a.ProjectId + AND p.UnitId = a.UnitId + AND p.WorkPostId = a.WorkPostId + AND p.PlanDate = a.IntoOutTime + AND (CHARINDEX(',' + p.UnitWorkId + ',', ',' + ISNULL(a.WorkAreaId, '') + ',') > 0 OR (ISNULL(a.WorkAreaId, '') = '' AND ISNULL(p.UnitWorkId, '') = '')) where p.Version = '" + Version + "'"; List listStr = new List(); if (!string.IsNullOrEmpty(this.ProjectId))