Сделать столбцы из диапазона дат - PullRequest
0 голосов
/ 16 января 2019

У меня есть 2 таблицы.

Первая таблица - это каталог моих транспортных средств, а вторая таблица, где у меня есть дата и показания одометра этого транспортного средства (может быть более 1 поездки в день на транспортное средство). Я хочу получить вывод, где я могу провести анализ того, есть ли у автомобиля показания одометра. Некоторые из них могут быть указаны как 0, что я хочу видеть, или даже вообще не иметь данных.

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

Я хотел бы получить вывод, подобный показанному ниже, где я могу видеть, какое транспортное средство имеет действительный одометр в день в указанном диапазоне дат. Было бы даже неплохо иметь общий столбец в конце, чтобы увидеть, какие из них не имеют одометра в этом диапазоне дат.

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

Ответы [ 3 ]

0 голосов
/ 16 января 2019

Поворот с левым соединением от Транспортных средств к Одометру, таким образом, все транспортные средства представлены в выходных данных

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
0 голосов
/ 16 января 2019

Для этого потребуется ДИНАМИЧЕСКИЙ SQL.

Столбцы указаны в МЕСЯЦАХ, но переходить на дни - дело незначительное.

Пример

-- 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)

Возвращает

enter image description here

РЕДАКТИРОВАТЬ - Запрошенное ОБНОВЛЕНИЕ

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)

РЕДАКТИРОВАТЬ-2 с новой колонкой

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)

Возвращает

enter image description here

0 голосов
/ 16 января 2019

Я подготовил сценарий относительно того, что вы хотите. Я использовал CTE и PIVOT, чтобы найти то, что вы хотите. Кроме того, я создал временную таблицу "Даты". Если вы планируете запускать этот отчет несколько раз, я советую вам создать статическую таблицу для повышения производительности. Я надеюсь, что этот метод может работать для вас.

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)
...