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
链接到一个基于 StartDate
的 OrderNo
任务时,它是 table.
中的一个 DateTime
字段
如果无法在一个 CASE
语句中同时检查 Route.No
和 JobSummary.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
在这里使用 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 方法在这方面肯定会更灵活。
编辑:重做整个问题。第一次带错了
结果应该是这样的:
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
链接到一个基于 StartDate
的 OrderNo
任务时,它是 table.
DateTime
字段
如果无法在一个 CASE
语句中同时检查 Route.No
和 JobSummary.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
在这里使用 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 方法在这方面肯定会更灵活。