T-SQL CASE 检查最年轻的日期,然后对照其他值

T-SQL CASE Check for youngest date and then against the other values

编辑:重做整个问题。第一次带错了

结果应该是这样的:

MachineName | OrderNo | TaskID | Code | NettoProd | BrutoProd | DiffProd
=========================================================================
F1            123456    101      O      100000      125000      25000
F1            123456    102      P8     1000000     1250000     250000
F1            123456    103      P1     10000       12500       2500
F1            123456    104      P4     100000      125000      25000

JobSummary有以下列:

StartDate 
TaskID

Route有以下列:

OrderNo 
TaskID

Resource 保存有关机器的数据

MachineID

如果我一开始就提供了所有详细信息,我已经添加了 Kyle Gobel 的部分,这是正确答案。

我想要完成的是显示一个 O,当它是第一个 taskID 链接到一个基于 StartDateOrderNo 任务时,它是 table.

中的一个 DateTime 字段

如果无法在一个 CASE 语句中同时检查 Route.NoJobSummary.StarDate,那么也可以为两者单独列一个。

查询

SELECT Resource.DESCRIPTION AS MachineName
    ,Route.OrderNo
    ,Route.TaskID
    ,CASE
        WHEN JobSummary.StartDate = (SELECT MIN(cr.StartDate) FROM JobSummary cr) THEN 'O'
        WHEN Route.No = 1 OR Route.No = 2 THEN 'P1'
        WHEN Route.No = 4 THEN 'P4'
        WHEN Route.No >= 8 THEN 'P8'
        ELSE '*FP*'
    END AS Code
    ,JobSummary.GoodProd As NettoProd
    ,JobSummary.GoodProd + JobSummary.SetupProd + JobSummary.WasteProd As BrutoProd
    ,(JobSummary.SetupProd + JobSummary.WasteProd) As DiffProd

FROM Route
JOIN Resource ON Resource.MachineID = Route.MachineID
JOIN JobSummary ON JobSummary.TaskID = Route.TaskID AND JobSummary.MachineID = Route.MachineID

通过阅读您的问题,您可能正在寻找 min 聚合函数。

case 
   when route.startDate = (select min(r.startdate) from table r) then 'O'
   when route.no = 1 or route.no = 2 then 'P1'
   ....
end as code

您可以将 ROW_NUMBER()PARTITION BY 结合使用,根据它的 StartDate 来识别第一个记录 taskID 对于 OrderNo 这样的 ROW_NUMBER()OVER(PARTITION BY Route.OrderNo ORDER BY JobSummary.StartDate ASC

示例数据和结构

CREATE TABLE [JobSummary] (MachineID INT,TaskID INT,StartDate DATETIME,GoodProd NUMERIC(18,0),SetupProd NUMERIC(18,0),WasteProd NUMERIC(18,0));
CREATE TABLE [Route] (OrderNo INT,MachineID INT,TaskID INT,[No] INT);
CREATE TABLE [Resource] (MachineID INT,DESCRIPTION CHAR(2));


INSERT INTO [Resource] VALUES(1,'F1');

INSERT INTO [Route] VALUES(123456,1,101,1);
INSERT INTO [Route] VALUES(123456,1,102,9);
INSERT INTO [Route] VALUES(123456,1,103,2);
INSERT INTO [Route] VALUES(123456,1,104,4);

INSERT INTO [JobSummary] VALUES(1,101,'20150101',100000,20000,5000);
INSERT INTO [JobSummary] VALUES(1,102,'20150103',1000000,200000,50000);
INSERT INTO [JobSummary] VALUES(1,103,'20150102',10000,2000,500);
INSERT INTO [JobSummary] VALUES(1,104,'20150103',100000,20000,5000);

查询

;WITH CTE AS 
(
SELECT Route.No
    ,Resource.[DESCRIPTION] AS MachineName
    ,Route.OrderNo
    ,Route.TaskID
    ,JobSummary.GoodProd As NettoProd
    ,JobSummary.GoodProd + JobSummary.SetupProd + JobSummary.WasteProd As BrutoProd
    ,(JobSummary.SetupProd + JobSummary.WasteProd) As DiffProd
    ,ROW_NUMBER()OVER(PARTITION BY Route.OrderNo ORDER BY JobSummary.StartDate ASC) rn
FROM Route
JOIN Resource ON Resource.MachineID = Route.MachineID
JOIN JobSummary ON JobSummary.TaskID = Route.TaskID AND JobSummary.MachineID = Route.MachineID
)
SELECT
    MachineName,
    OrderNo,
    TaskID,
    CASE
        WHEN rn = 1 THEN 'O'
        WHEN No IN (1,2) THEN 'P1'
        WHEN No = 4 THEN 'P4'
        WHEN No >= 8 THEN 'P8'
        ELSE '*FP*'
    END AS Code,
    NettoProd,
    BrutoProd,
    DiffProd
FROM CTE
ORDER BY OrderNo,TaskID

输出

MachineName OrderNo TaskID  Code    NettoProd   BrutoProd   DiffProd
F1  123456  101 O   100000  125000  25000
F1  123456  102 P8  1000000 1250000 250000
F1  123456  103 P1  10000   12500   2500
F1  123456  104 P4  100000  125000  25000

SQL Fiddle

在这里使用 ROW_NUMBER 可能是一个很好的起点,但由于您只想检查第一个 StartDate,因此使用 MIN() OVER 可能是更好的主意。您发布的查询只需要一个小改动(强调):

SELECT Resource.DESCRIPTION AS MachineName
    ,Route.OrderNo
    ,Route.TaskID
    ,CASE
        WHEN JobSummary.StartDate = <b>MIN(JobSummary.StartDate) OVER (PARTITION BY Route.OrderNo)</b> THEN 'O'
        WHEN Route.No = 1 OR Route.No = 2 THEN 'P1'
        WHEN Route.No = 4 THEN 'P4'
        WHEN Route.No >= 8 THEN 'P8'
        ELSE '*FP*'
    END AS Code
    ,JobSummary.GoodProd As NettoProd
    ,JobSummary.GoodProd + JobSummary.SetupProd + JobSummary.WasteProd As BrutoProd
    ,(JobSummary.SetupProd + JobSummary.WasteProd) As DiffProd

FROM Route
JOIN Resource ON Resource.MachineID = Route.MachineID
JOIN JobSummary ON JobSummary.TaskID = Route.TaskID AND JobSummary.MachineID = Route.MachineID
;

也许 PARTITION BY 也需要包括 Resource.DESCRIPTION——很难从一个小例子中判断出来。

上述查询可能比 ROW_NUMBER 方法运行得更快。这是因为 ROW_NUMBER 子集需要完全排序,而 MIN() OVER 只会从每个子集中查找单个值。

另一方面,如果您以后可能需要第二行、第三行等的特殊条件,ROW_NUMBER 方法在这方面肯定会更灵活。