Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make columns out of a date range

I have 2 tables.

The first table is a directory of my vehicles, and the second one is a table where I have the date and odometer reading of that vehicle (there might be more than 1 trip per day per vehicle). I want to have an output where I can have some analysis of whether a vehicle has odometer readings. Some of them could be reported as 0, which is what I want to be able to see or even maybe have no data at all.

TBLVehicles:

Vehicle       Group
-----------------
100             A
101             A
102             B
103             B
104             C
105             C

TBLTrips:

Vehicle    StartDate    Odometer
-----------------------------------------
100        2018-01-12    100
101        2018-05-12    1000
101        2018-05-12    1010
103        2018-05-12    500
103        2018-06-12    505
105        2018-06-12    0
105        2018-06-12    0

I would like getting an output like the one below where I can see which vehicle has a valid odometer per day in a specified date range. It would even be nice to have a total column at the end to see which ones have absolutely no odometer in that date range.

OUTPUT

Vehicle     Group   2018-01-12  2018-02-12  2018-03-12  2018-04-12  2018-05-12  2018-06-12
----------------------------------------------------------------------------------
100          A         1          0          0            0           0         0
101          A         0          0          0            0           2         0
102          B         0          0          0            0           0         0
103          B         0          0          0            0           1         1
104          C         0          0          0            0           0         0
105          C         0          0          0            0           0         2
like image 520
pato.llaguno Avatar asked Jan 31 '26 18:01

pato.llaguno


1 Answers

This one would require DYNAMIC SQL.

The columns are MONTHS, but it is a small matter to switch to days.

Example

-- Generate Date Full Date Range
Declare @D1 date,@D2 date
Select @D1=Min(StartDate),@D2=Max(StartDate) from TBLTrips

Select Top (DateDiff(Month,@D1,@D2)+1) D=DateAdd(Month,-1+Row_Number() Over (Order By (Select Null)),@D1) 
 Into  #Dates
 From  master..spt_values n1


-- Generate Columns
Declare @Cols varchar(max) = stuff( (Select ','+QuoteName(D) From #Dates Order by 1 For XML Path('')),1,1,'')  

-- Generate Dynamic SQL
Declare @SQL varchar(max) = '
Select *
 From (
        Select Vehicle,StartDate,Odometer=sign(Odometer) From TBLTrips
        Union 
        Select A.Vehicle 
              ,B.D
              ,0
         From  TBLVehicles A
         Cross Join #Dates B
      ) Src
 Pivot (sum([Odometer]) For [StartDate] in (' + @Cols  + ') ) p
 Cross Apply ( Select Total = '+replace(@Cols,',','+')+' ) T 
'
--Print @SQL 
Exec(@SQL)

Returns

enter image description here

EDIT - Requested UPDATE

Declare @D1 date,@D2 date
Select @D1=Min(convert(Date,TripStart)),@D2=Max(convert(Date,TripStart)) from EMS_trip_Data2

Select Top (DateDiff(DAY,@D1,@D2)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),@D1) 
 Into  #Dates
 From  master..spt_values n1


-- Generate Columns
Declare @Cols varchar(max) = stuff( (Select ','+QuoteName(D) From #Dates Order by 1 For XML Path('')),1,1,'')  


-- Generate Dynamic SQL
Declare @SQL varchar(max) = '
Select *
 From (
        Select Vehicle,TripStart=convert(Date,TripStart),StartOdometer=sign(StartOdometer) From EMS_trip_Data2
        Union 
        Select A.Vehicle 
              ,B.D
              ,0
         From  VehicleSummary2 A
         Cross Join #Dates B
      ) Src
 Pivot (sum([StartOdometer]) For [TripStart] in (' + @Cols  + ') ) p
 Cross Apply ( Select Total = '+replace(@Cols,',','+')+' ) T 
'
--Print @SQL 
Exec(@SQL)

EDIT-2 With New Column

Declare @D1 date,@D2 date
Select @D1=Min(convert(Date,TripStart)),@D2=Max(convert(Date,TripStart)) from EMS_trip_Data2

Select Top (DateDiff(DAY,@D1,@D2)+1) D=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),@D1) 
 Into  #Dates
 From  master..spt_values n1


-- Generate Columns
Declare @Cols varchar(max) = stuff( (Select ','+QuoteName(D) From #Dates Order by 1 For XML Path('')),1,1,'')  


-- Generate Dynamic SQL
Declare @SQL varchar(max) = '
Select *
 From (
        Select Src1.*,VS.[Group]
         From  (
                Select Vehicle,TripStart=convert(Date,TripStart),StartOdometer=sign(StartOdometer) From EMS_trip_Data2
                Union 
                Select A.Vehicle 
                      ,B.D
                      ,0
                 From  VehicleSummary2 A
                 Cross Join #Dates B
                ) src1
         Join VehicleSummary2 VS on src1.Vehicle = VS.Vehicle
      ) Src
 Pivot (sum([StartOdometer]) For [TripStart] in (' + @Cols  + ') ) p
 Cross Apply ( Select Total = '+replace(@Cols,',','+')+' ) T 
'
--Print @SQL 
Exec(@SQL)

Returns

enter image description here

like image 198
John Cappelletti Avatar answered Feb 02 '26 10:02

John Cappelletti



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!