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
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
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
I have prepared a script regarding what you want. I have used CTE
and PIVOT
to find what you want. Also, I have created "Dates" temp table. If you planning to run this report multiple time I advise you to create a static table to increase the performance. I hope this method can work for you.
IF OBJECT_ID('TEMPDB..#TBLVehicles') IS NOT NULL
DROP TABLE #TBLVehicles;
CREATE TABLE #TBLVehicles
(
VehicleId INT
);
INSERT INTO #TBLVehicles
VALUES (100),(101),(102),(103),(104),(105);
IF OBJECT_ID('TEMPDB..#TBLTrips') IS NOT NULL
DROP TABLE #TBLTrips;
CREATE TABLE #TBLTrips
(
VehicleId INT
,StartDate DATE
,Odometer INT
);
INSERT INTO #TBLTrips
VALUES
(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 );
DECLARE @SQLString NVARCHAR(MAX)
DECLARE @DateArray VARCHAR(MAX)
DECLARE @StartDate DATE='2018-01-12'
DECLARE @EndDate DATE='2018-06-12'
IF OBJECT_ID('TEMPDB..#Dates') IS NOT NULL
DROP TABLE #Dates;
CREATE TABLE #Dates
(
Date DATE
);
WHILE @StartDate<=@EndDate
BEGIN
INSERT INTO #Dates
SELECT @StartDate
SET @StartDate = DATEADD(DAY,1,@StartDate)
END
SELECT @DateArray=ISNULL(@DateArray+',','')+'['+CAST(Date AS VARCHAR)+']' FROM #Dates ;
SET @SQLString=
'
WITH CTE AS
(
SELECT V.VehicleId
,T1.Date
,CASE WHEN T2.Odometer IS NULL THEN 0 ELSE 1 END OdometerKey
FROM #TBLVehicles V
LEFT JOIN FROM #Dates T1 ON 1=1
LEFT JOIN #TBLTrips T2 ON V.VehicleId = T2.VehicleId AND T1.Date=T2.StartDate
)
SELECT * FROM CTE
PIVOT
(SUM(OdometerKey) FOR Date IN ('+@DateArray+')
) PVT
';
EXEC SP_EXECUTESQL @SQLString
--PRINT(@SQLString)
Pivot with a left join from Vehicles to Odometer so all vehicles are represented in the output
Create Table Vehicle
(
Id Int
)
Insert Into Vehicle Values
(100),
(101),
(102),
(103),
(104),
(105)
Create Table Odometer
(
Vehicle_Id Int,
StartDT Date,
Odometer Int
)
Insert Into Odometer Values
(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);
Select
id ,
[2018-01-12],
[2018-02-12],
[2018-03-12],
[2018-04-12],
[2018-05-12],
[2018-06-12],
[2018-07-12],
[2018-08-12],
[2018-09-12],
[2018-10-12],
[2018-11-12],
[2018-12-12],
(
isnull([2018-01-12],0)+
isnull([2018-02-12],0)+
isnull([2018-03-12],0)+
isnull([2018-04-12],0)+
isnull([2018-05-12],0)+
isnull([2018-06-12],0)+
isnull([2018-07-12],0)+
isnull([2018-08-12],0)+
isnull([2018-09-12],0)+
isnull([2018-10-12],0)+
isnull([2018-11-12],0)+
isnull([2018-12-12],0)
) As Total
From
(
Select * From Vehicle v Left Join
Odometer o On v.Id = o.Vehicle_Id
) p
Pivot
(
count(Odometer)
For StartDT In ([2018-01-12],[2018-02-12],[2018-03-12],[2018-04-12],[2018-05-12],[2018-06-12],[2018-07-12],[2018-08-12],[2018-09-12],[2018-10-12],[2018-11-12],[2018-12-12])
) pv
order by pv.id
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.