2015-06-03 11 views
5

EDYCJA: Przeformułuj całe pytanie. Za pierwszym razem przyszło to źle.T-SQL CASE Sprawdź najmłodszą datę, a następnie w porównaniu z innymi wartościami

W Wyniki powinno być tak:

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 

The JobSummary ma następujące kolumny:

StartDate 
TaskID 

Route ma następujące kolumny:

OrderNo 
TaskID 

Resource przechowuje dane o maszynach

MachineID 

już dodanych część Kyle Gobel, która była prawidłowa odpowiedź, gdybym pod warunkiem, wszystkie szczegóły w pierwszej kolejności.

Co chciałbym osiągnąć to, aby pokazać O kiedy to pierwszy taskID zadań związanych z jednym OrderNo oparciu o StartDate, który jest DateTime pola w tabeli.

Jeśli niemożliwe jest sprawdzenie obu Route.No i JobSummary.StarDate w jednym oświadczeniu CASE, to osobna kolumna dla obu również.

Zapytanie

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 
+1

Jeśli możesz podać nam zapytanie, co nie działa, a oczekiwane wyniki, prawdopodobnie uzyskasz dobrą odpowiedź. –

+2

Nie widzę odniesienia do StartDate lub kodu "O" w powyższym przykładzie; czy możesz opublikować pełniejszy przykład tego, co próbujesz zrobić? –

Odpowiedz

3

Można użyć ROW_NUMBER() z PARTITION BY zidentyfikować pierwszy rekord taskID na podstawie jego StartDate dla OrderNo jak ten Danych ROW_NUMBER()OVER(PARTITION BY Route.OrderNo ORDER BY JobSummary.StartDate ASC

Sample and 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); 

Zapytanie

;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 

Wyjście

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

+0

Nigdy bym tego nie odkrył. Pójdę zbadać część partycji w Internecie. Dzięki. – Ignotus

2

Od czytania pytanie, być może szuka funkcji zbiorczej 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 
1

Korzystanie ROW_NUMBER może być dobrym punktem wyjścia, ale jak chcesz sprawdzić tylko za pierwszym StartDate, może być lepszym pomysłem zamiast tego użyj MIN() OVER.Twój wysłane zapytanie musiałaby jedynie niewielką zmianę (podkreślone):

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 
;

Może partycję musiałaby zawierać Resource.DESCRIPTION jak dobrze - trudno powiedzieć od małego przykładu.

Powyższe zapytanie potencjalnie zadziała szybciej niż metoda ROW_NUMBER. Wynika to z tego, że z ROW_NUMBER podzbiory będą musiały być całkowicie posortowane, podczas gdy MIN() OVER będzie szukał tylko jednej wartości z każdego podzbioru.

Z drugiej strony, jeśli jest szansa, że ​​będziesz później potrzebował specjalnego warunku dla drugiego, trzeciego itd. Wiersza, metoda ROW_NUMBER z pewnością byłaby bardziej elastyczna pod tym względem.

Powiązane problemy