EDIT: refaire toute la question. L'a amené dans le mauvais sens la première fois.
Les résultats devraient être comme:
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
Le JobSummary
a les colonnes suivantes:
StartDate TaskID
La Route
a les colonnes suivantes:
OrderNo TaskID
La Resource
contient datatables sur les machines
MachineID
J'ai déjà ajouté la partie de Kyle Gobel, qui était la bonne réponse, si j'avais fourni tous les détails en premier lieu.
Ce que je voudrais accomplir est d'afficher un O
quand c'est le premier taskID
des tâches liées à un OrderNo
basé sur le StartDate
, qui est un champ DateTime
dans la table.
S'il est impossible de vérifier à la fois Route.No
et JobSummary.StarDate
dans une instruction CASE
, une colonne séparée pour les deux le fera également.
Question
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
Vous pouvez utiliser ROW_NUMBER()
avec PARTITION BY
pour identifier le premier taskID
logging basé sur son StartDate
pour un OrderNo
comme ceci ROW_NUMBER()OVER(PARTITION BY Route.OrderNo ORDER BY JobSummary.StartDate ASC
Échantillon de données et de structure
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);
Question
;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
Sortie
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
En lisant votre question, vous pourriez être à la search de la fonction d'agrégat 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
Utiliser ROW_NUMBER peut être un bon sharepoint départ ici, mais comme vous ne voulez vérifier que le premier StartDate
, il peut être préférable d'utiliser MIN() OVER
place. Votre requête publiée n'aurait besoin que d'un petit changement (souligné):
SELECT Resource.DESCRIPTION AS MachineName ,Route.OrderNo ,Route.TaskID ,CASE WHEN JobSummary.StartDate = MIN(JobSummary.StartDate) OVER (PARTITION BY Route.OrderNo) 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 ;
Peut-être que le PARTITION BY devrait inclure Resource.DESCRIPTION
aussi – difficile à dire à partir d'un petit exemple.
La requête ci-dessus fonctionnera potentiellement plus rapidement que la méthode ROW_NUMBER. Cela est dû au fait que les sous-sets ROW_NUMBER doivent être complètement sortingés, alors que MIN () OVER ne searchrait qu'une seule valeur de chaque sous-set.
D'un autre côté, s'il y a une chance que vous ayez besoin d'une condition spéciale pour une seconde, une troisième, etc., la méthode ROW_NUMBER sera certainement plus flexible à cet égard.