Sql server 如何编写T-SQL将工具提示的数据带回原始数据集?
我正在T-SQL中编写一个SP,以从存储在SQLServer2008R2上的数据库表中的测试数据中恢复“首次通过率”指标。我编写SP是为了返回应用程序中绘图的基本数据,但我想添加工具提示,以提供用户悬停在图形段上的特定时间段的详细信息 注意——这里我不是问如何做UI部分,而是问如何获取数据。UI的东西我以后会处理 以下是存储原始数据的简化模式:Sql server 如何编写T-SQL将工具提示的数据带回原始数据集?,sql-server,tsql,sql-server-2008r2-express,Sql Server,Tsql,Sql Server 2008r2 Express,我正在T-SQL中编写一个SP,以从存储在SQLServer2008R2上的数据库表中的测试数据中恢复“首次通过率”指标。我编写SP是为了返回应用程序中绘图的基本数据,但我想添加工具提示,以提供用户悬停在图形段上的特定时间段的详细信息 注意——这里我不是问如何做UI部分,而是问如何获取数据。UI的东西我以后会处理 以下是存储原始数据的简化模式: CREATE TABLE [dbo].[TestRecords]( [TestRecordID] [int] NOT NULL, [Ho
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
注意:在保存详细记录之前,我需要创建主/父记录并将其保存到磁盘,因此我有外键值FpyValueID
我可以想象的一种方法是改变我计算原始数据的方式,并从细节记录中求和数据,以计算总体FPY值。我还可以看到在哪里可能需要使用GROUPBY指令来获取细节值
有没有人对如何构造SQL查询以在不添加更多循环的情况下将这些数据拉回来提出建议?这已经很长时间了,所以我要离开这里。如果您需要更多信息,请询问
提前感谢您的任何想法/帮助,
Dave在这里,我尝试了一下您的第一个要求: 返回第一次正确建造的总单元数除以建造的总单元数-这是第一次通过的产量数
可能有一种更有效的方法来处理强制转换。这个问题太长,包含了太多不必要的信息。我不只是删除它,而是选择发布我为解决问题所做的事情,以防有人有足够的空闲时间实际阅读问题和答案 将从WCF服务调用此SP,并将结果数据集从该服务返回给客户端。因此,没有必要同时做所有事情。我计划做的是在第二个过程中使用在第一个过程中创建的内存表来创建细节记录。会话ID返回给WCF服务,然后WCF服务读取记录集,将数据返回给客户端,并删除数据库中的工作记录 粗糙但有效。如果我想出一个更巧妙的方法来做这件事,我会回来张贴它
玩得开心 谢谢,但我已经在发布的SQL代码中找到了这一部分。我在帖子中没有包括该部分的其他几个要求,因为我已经让它工作了。我真正需要的是一些关于如何获得支持细节以及FPY值的想法。。。不过,我确实喜欢使用十进制类型而不是浮点类型的想法。我最喜欢的文章中有你的问题,我想回来回答,但每次我回答的时候,我都看到它有多大,很难深入研究这个问题。有什么方法可以修剪它吗?我将尝试将其简化为一个更简单的数据集,这样就不会有太多的噪音。里面真的有很多东西分散了人们对真正问题的注意力。我被另一个火热的项目转移了注意力,但很快就会回到这个话题上。
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)
SELECT COUNT(TestRecordID) as UnitsPassed,CAST(CAST(COUNT(TestRecordID) AS DECIMAL(6,3)) / (SELECT COUNT(TestRecordID) FROM TestRecords) AS DECIMAL(6,3)) as FirstPassYield
FROM TestRecords
WHERE PassFailStatus = 1 AND testDateTime > '12/06/2011' AND testDateTime < 12/07/2011'