我正在用 T-SQL 编写一个 SP,以便从存储在 SQL Server 2008 R2 的数据库表中的测试数据中恢复“首次通过率”指标。我编写了 SP 以返回用于在应用程序中绘制图形的基本数据,但我想添加工具提示以在用户将鼠标悬停在图形段上时提供特定时间段的详细信息。
注意 - 我不是在这里问如何做 UI 部分,只是问如何获取数据。UI 的东西我稍后会处理...
这是用于存储原始数据的简化模式:
CREATE TABLE [dbo].[TestRecords](
[TestRecordID] [int] NOT NULL,
[HostName] [varchar](25) NOT NULL,
[UnitSerial] [varchar](20) NOT NULL,
[PassFailStatus] [bit] NOT NULL,
[AssyLineID] [int] NOT NULL,
[TestDateTime] [datetime] NOT NULL)
这个想法是返回第一次正确构建的单元总数除以构建的单元总数 - 这是第一次通过的产量数。我们希望在任意时间段内对任意数量的装配线 (AssyLineID) 执行此操作。
在这种情况下,“任意”是指在给定的一天内每小时或在较长时间内每天...
生成的数据集是一个记录表,如下所示:
CREATE TABLE [dbo].[FpyValues](
[FpyValueID] [int] IDENTITY(1,1) NOT NULL,
[SessionID] [int] NOT NULL,
[DateTime] [datetime] NOT NULL,
[AssyLineID] [int] NOT NULL,
[Fpy] [float] NOT NULL,
[TotalUnits] [int] NOT NULL,
[FailedUnits] [int] NOT NULL)
到目前为止一切顺利,但返回的 FPY 值并没有包含太多信息。对于有趣的事件(相对较低或较高的 FPY),质量团队想知道他们正在建造什么样的单位以及使用哪些数字来获得 FPY——无需查阅另一份报告。当要显示工具提示时,我可以返回数据库,但数据不会相同。原始数据集考虑了在较早时间段内失败的单元,并且不(错误地)将其视为当前时间段的良好单元。
这是我的 SP 的一个简化版本,用于获取给定日期的每小时 FPY:
ALTER PROCEDURE [dbo].[GetHourlyFpy]
@ProdLineList VARCHAR(100),
@ReportDate DATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE @Fpy FLOAT, @Total FLOAT, @Failed FLOAT
DECLARE @SessionID INT;
DECLARE @TempList TABLE
(
LineID INT
);
DECLARE @LineID VARCHAR(10);
DECLARE @LineName VARCHAR(16);
DECLARE @FailedUnits TABLE
(
UnitSerial VARCHAR(12)
);
DECLARE @Start INT, @End INT, @Current INT;
DECLARE @StartTime DATETIME, @EndTime DATETIME;
-- unpack incoming comma-separated list of Production Line IDs into temp table
-- get session ID to identify results for this session
-- get the start and end hour values (@Start and @End)
-- Get the Date part of the incoming DATETIME value (time = 00:00:00.000)
-- loop through all production lines, creating result records as we go
WHILE EXISTS(SELECT * FROM @TempList)
BEGIN
SELECT TOP 1 @LineID = LineID FROM @TempList;
-- clear the failed units table
DELETE FROM @FailedUnits;
-- set the start time for reporting
SET @StartTime = (SELECT DATEADD(Hh, @Start, @ReportDate));
-- loop through all 1-hour periods for the day
SET @Current = @Start;
WHILE @Current < @End
BEGIN
SET @EndTime = (SELECT DATEADD(Hh, 1, @StartTime));
SET @Total = (SELECT COUNT(DISTINCT tr.UnitSerial)
FROM TestRecords
WHERE @StartTime <= tr.TestDateTime
AND tr.TestDateTime < @EndTime
AND tr.AssyLineID = @LineID
AND (NOT EXISTS
(SELECT UnitSerial FROM @FailedUnits f WHERE tr.UnitSerial = f.UnitSerial)));
SET @Failed = (SELECT COUNT(DISTINCT tr.UnitSerial)
FROM TestRecords tr
WHERE @StartTime <= tr.TestDateTime
AND tr.TestDateTime < @EndTime
AND tr.PassFailStatus = 0
AND tr.AssyLineID = @LineID
AND (NOT EXISTS
(SELECT UnitSerial FROM @FailedUnits f WHERE tr.UnitSerial = f.UnitSerial)));
-- populate the failed units list as needed
INSERT INTO @FailedUnits
SELECT DISTINCT tr.UnitSerial
FROM dbo.TestRecords tr
LEFT OUTER JOIN
@FailedUnits f ON tr.UnitSerial = f.UnitSerial
WHERE @StartTime <= tr.TestDateTime
AND tr.TestDateTime < @EndTime
AND tr.PassFailStatus = 0
AND tr.AssyLineID = @LineID
AND f.UnitSerial IS NULL;
IF (0 = @Total)
SET @Fpy = 0;
ELSE
SET @Fpy = (@Total - @Failed) / @Total;
INSERT INTO dbo.FpyValues (SessionID, [DateTime], ProductionLine, Fpy, TotalUnits, FailedUnits)
VALUES(@SessionID, @StartTime, @LineID, @Fpy, @Total, @Failed);
SET @StartTime = (SELECT DATEADD(Hh, 1, @StartTime));
SET @Current = @Current + 1;
END
-- we're done with this production line
DELETE FROM @TempList WHERE LineID = @LineID;
END
RETURN @SessionID;
END
我需要一种方法来为每个时间段的每条装配线填充详细信息,如下所示:
CREATE TABLE [dbo].[FpyUnits](
[FpyUnitID] [int] IDENTITY(1,1) NOT NULL,
[FpyValueID] [int] NOT NULL,
[DateTime] [datetime] NOT NULL,
[AssyLineID] [int] NOT NULL,
[UnitType] [varchar](25) NOT NULL,
[TotalUnits] [int] NOT NULL,
[FailedUnits] [int] NOT NULL)
注意我需要在保存详细记录之前创建主/父记录并将其保存到磁盘,所以我有外键值(FpyValueID)。
我可以想象的一种方法是更改从详细记录计算原始数据和 SUM 数据的方式,以计算总体 FPY 值。我还可以看到我可能需要在哪里使用 GROUP BY 指令来获取详细值。
有没有人对如何构建 SQL 查询以在不添加更多循环的情况下拉回这些数据有建议?这已经很长了,所以我会在这里退出。如果您需要更多信息,请询问...
提前感谢您的任何想法/帮助,戴夫