Рассмотрим это решение с несколькими CTE, в котором запланированные и фактические производные таблицы становятся CTE, а новый оператор date_ranks включает в себя ROWNUMBER()
оконную функцию с PARITION BY
и ORDER BY
.Столбцы разделов отражают GROUP BY
столбцов в , запланированных для ранжирования дат заказа в той же группе.
Затем в основном запросе верхнего уровня выполните INNER JOIN
, используя date_ranks для тех же столбцов GROUP BY
, выбирая только где rank = 2.
WITH planned AS (
SELECT orgDay.LOCALDAY
, pet.WORKRESOURCEID
, orgDay.ORGANIZATIONID
, min(pet.Starttime) min_StartTime
, max(pet2.Endtime) max_EndTime
, DateDiff(HH, orgDay.StartTime, orgDay.LocalDay) tz_offset
FROM dbo.PLANNEDEVENTTIMELINE pet
INNER JOIN dbo.organizationday orgDay
ON orgDay.ID = pet.ORGANIZATIONDAYID
WHERE orgDay.LocalDay = CAST(DateAdd(DAY, -1, GETDATE()) as DATE)
GROUP BY orgday.localday
, orgday.starttime
, pet.WORKRESOURCEID
, orgDay.ORGANIZATIONID
),
actual AS (
SELECT spDay.Localday
, c.Name Campaign
, aet.EmployeeID
, min(aet.starttime) min_StartTime
, max(aet.endtime) max_endtime
FROM dbo.ACTUALEVENTTIMELINE aet
LEFT JOIN dbo.ORGANIZATIONDAY spDay
ON spDay.ID = aet.SPDAYID AND aet.ISPAID != 0
INNER JOIN dbo.sp sp
ON sp.sid = spday.SPID
INNER JOIN dbo.campaign c
ON c.id = sp.CAMPAIGNID
WHERE spDay.LocalDay = CAST(DateAdd(DAY, -1, GETDATE()) as DATE)
GROUP BY spday.localday
, c.name
, aet.EMPLOYEEID
),
date_ranks AS (
SELECT orgday.localday
, orgday.starttime
, pet.WORKRESOURCEID
, orgDay.ORGANIZATIONID
, pet.Endtime
, ROW_NUMBER() OVER(PARTITION BY orgday.localday
, orgday.starttime
, pet.WORKRESOURCEID
, orgDay.ORGANIZATIONID
ORDER BY pet.Endtime DESC) AS rank
FROM dbo.PLANNEDEVENTTIMELINE pet
INNER JOIN dbo.organizationday orgDay
ON orgDay.ID = pet.ORGANIZATIONDAYID
WHERE orgDay.LocalDay = CAST(DateAdd(DAY, -1, GETDATE()) as DATE)
)
SELECT Cast(planned.LOCALDAY AS DATE) [Day]
, actual.Campaign
, org.Name Organization
, eAM.EMPLOYEENUMBER SalesID
, p.LastName + ', ' + p.FirstName Employee
, DateAdd(HH, planned.tz_offset, planned.min_starttime) PlannedStart
, DateAdd(HH, planned.tz_offset, actual.min_StartTime) ActualStart
, DateAdd(HH, planned.tz_offset, planned.max_endtime) PlannedEnd
, DateAdd(HH, planned.tz_offset, dr.pet.Endtime) Second_Recent_PlannedEnd -- NEW COLUMN
, DateAdd(HH, planned.tz_offset, actual.max_EndTime) ActualEnd
FROM planned
INNER JOIN actual
ON planned.LOCALDAY = actual.LOCALDAY
AND planned.WORKRESOURCEID = actual.EMPLOYEEID
INNER JOIN date_ranks dr -- NEW JOIN
ON planned.LOCALDAY = dr.LOCALDAY
AND planned.WORKRESOURCEID = dr.WORKRESOURCEID
AND planned.starttime = dr.starttime
AND planned.ORGANIZATIONID = dr.ORGANIZATIONID
AND dr.rank = 2
INNER JOIN dbo.ORGANIZATION org
ON org.id = planned.ORGANIZATIONID
AND org.Name LIKE '%CPO%'
INNER JOIN dbo.EMPLOYEEAM eam
ON eam.id = planned.WORKRESOURCEID
INNER JOIN dbo.person p
ON p.id = eam.personid
ORDER BY 1, 2, 3, 5