T-SQL CASE Vérifiez la date la plus jeune et ensuite les autres valeurs

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.