Home > Software engineering >  SQL query to get the start and end date from tasks labeled 'D' if they exist, and the mini
SQL query to get the start and end date from tasks labeled 'D' if they exist, and the mini

Time:04-08

I am trying to query my data so that it obtains the start and end date for each job and cost code. I want one start and end date for each JobNumber and CostCode. If one of the rows contains a Status of 'D' then I would like that StartDate and EndDate to be the final StartDate and EndDate for that JobNumber and CostCode. If a JobNumber and CostCode combination does not contain a Status of 'D' then I would just like to return the minimum StartDate and EndDate of all instances of the JobNumber and CostCode.

The data is grouped by JobNumber, CostCode, and Status so there are no duplicates of these three columns. Additionally only the 'D' Status rows will contain an EndDate so the resultant EndDate should always be the 'D' row or Null. The table looks like this:

JobNumber CostCode Status StartDate EndDate
566169 053800 D 2021-10-08 00:00:00.000 2021-10-18 14:01:55.517
566170 010800 D 2022-05-18 00:00:00.000 2022-05-22 15:38:58.447
566170 010800 B 2022-04-04 00:00:00.000 NULL
566170 026200 B 2022-04-21 00:00:00.000 NULL
566170 026200 A 2022-05-06 00:00:00.000 NULL
566175 033500 A NULL NULL

And the result should look like this:

JobNumber CostCode StartDate EndDate
566169 053800 2021-10-08 00:00:00.000 2021-10-18 14:01:55.517
566170 010800 2022-05-18 00:00:00.000 2022-05-22 15:38:58.447
566170 026200 2022-04-21 00:00:00.000 NULL
566175 033500 NULL NULL

I have been stuck on this a while and am not very experienced with SQL so am having trouble. I have attempted joining it to itself and CASE statements with a GROUP BY on JobNumber and CostCode but have had no luck either way. Any help would be greatly appreciated.

CodePudding user response:

SELECT JobNumber, CostCode, Status, StartDate, EndDate
FROM (
    SELECT JobNumber, CostCode, Status, StartDate, EndDate
        , row_number() over 
            (
                partition by JobNumber, CostCode 
                order by case when status='D' then 0 else 1 end, StartDate, EndDate
            ) rn
    FROM [table]
) t
WHERE rn = 1

See it run here:

https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=75cfbf2f3519da7acc116fc8e6047f75

CodePudding user response:

I would use a cursor for each job. If there is a D record for that job then select that start and enddate, else select startdate and endate where the startdate is equal to the min start date for that job.

CodePudding user response:

Use a traditional UNION. And CONCAT for SQL server .

SELECT
   jobNumber,
   costCode,
   max(startdate) as startdate,
   max(enddate) as enddate
from tablename
where status = 'D'
group by jobNumber, costcode
UNION
select
   jobnumber,
   costcode,
   min(startdate) as startdate,
   min(enddate) as enddate
from tablename
where CONCAT(jobNumber,':',costCode) not in (SELECT CONCAT(jobNumber,':',costCode) from tablename where status='D')
group by jobnumber, costcode

Fiddle here

  • Related