I have been banging my head on this for a while now and I think I've drastically over-complicating things at this point. What I have is a table containing the fields
OpenDate
ClosedDate
Client
Contract
Service
What I need to turn that into is
Date
Client
Contract
Service
OpenedOnThisDay
OpenedYesterday
ClosedOnThisDay
ClosedYesterday
OpenAtStartOfTomorrow
OpenAtStartOfToday
For any given Date, there may or may not be any issues opened or closed ON that day. That day should still be included with 0's
I have come at this a number of ways and can produce one of the desired results at a time (opened on, closed on, Open at end of), but I cannot get them all at once, at least not without exponentially increasing the query time.
My queries currently as views are as follows
Opened On
select Cast(EntryDateTime as Date) as DateStamp
,ContractNumber
,Client
,services.Service
,sum(1) as Count
,lag(sum(1)) OVER (
partition by tickets.ContractNumber
,services.Service ORDER BY Cast(EntryDateTime as Date) ASC
) as CountDayBefore
from v_JiraImpactedServices as services
LEFT JOIN v_JiraTickets as tickets ON services.ticketnumber = tickets.TicketNumber
WHERE tickets.Client is not null
AND tickets.TicketNumber IS NOT NULL
and tickets.ContractNumber is not null
GROUP BY Cast(tickets.EntryDateTime as Date)
,tickets.ContractNumber
,tickets.Client
,services.Service;
Closed On
select Cast(ResolvedDateTime as Date) as DateStamp
,ContractNumber
,Client
,services.Service
,sum(1) as Count
,lag(sum(1)) OVER (
partition by tickets.ContractNumber
,services.Service ORDER BY Cast(ResolvedDateTime as Date) ASC
) as CountDayBefore
from v_JiraImpactedServices as services
LEFT JOIN v_JiraTickets as tickets ON services.ticketnumber = tickets.TicketNumber
WHERE tickets.Client is not null
and tickets.TicketNumber is not null
AND tickets.ContractNumber is not null
GROUP BY Cast(tickets.ResolvedDateTime as Date)
,tickets.ContractNumber
,tickets.Client
,services.Service;
Open On
SELECT calendar.FullDate as DateStamp
,tickets.ContractNumber
,tickets.client
,services.Service
,IsNull(count(tickets.TicketNumber), 0) as Count
,IsNull(lag(count(tickets.TicketNumber), 1) OVER (
partition by tickets.ContractNumber
,services.Service Order By FullDate ASC
), 0) as CountDayBefore
FROM v_Calendar as calendar
LEFT JOIN v_JiraTickets as tickets ON Cast(tickets.EntryDateTime as Date) <= calendar.FullDate
AND (
Cast(tickets.ResolvedDateTime as Date) > calendar.FullDate
OR tickets.ResolvedDateTime is null
)
LEFT JOIN v_JiraImpactedServices as services ON services.ticketnumber = tickets.TicketNumber
WHERE tickets.Client is not null
AND tickets.ContractNumber is not null
GROUP BY calendar.FullDate
,tickets.ContractNumber
,tickets.Client
,services.Service;
As I said each of these by itself gives ALMOST the desired results, but omits days with 0 values.
Aside from producing days with 0 values, I need to also combine these into a single table result. All attempts so far have either produced obviously wrong JOIN results, or takes an hour to execute.
I would be most grateful if someone could point me in the right direction here.
Just to give you an idea, although the fieldnames don't match your scenario, this is how I would approach this:
WITH
SourceData (ClientID, ContractID, ServiceID, DateStamp) AS (
SELECT a.ID, b.ID, c.ID, d.DateStamp
FROM clients a
JOIN contracts b ON a.ID = b.ClientID
JOIN [services] c ON b.ID = c.ContractID
CROSS JOIN calendar d
WHERE d.DateStamp >= DATEADD(day, -60, GETDATE())
)
SELECT d.DateStamp, s.ClientID, s.ContractID, s.ServiceID
, COUNT(CASE WHEN Cast(EntryDateTime as Date) = d.DateStamp THEN 1 END) AS OpenedOn
, COUNT(CASE WHEN Cast(ResolvedDateTime as Date) = d.DateStamp THEN 1 END) AS ClosedOn
, COUNT(CASE WHEN Cast(ResolvedDateTime as Date) > d.DateStamp OR ResolvedDateTime IS NULL AND EntryDateTime IS NOT NULL THEN 1 END) AS InProgress
FROM SourceData s
LEFT JOIN tickets t
ON s.ClientID = t.ClientID
AND s.ContractID = t.ContractID
AND s.ServiceID = t.ServiceID
AND s.DateStamp >= Cast(EntryDateTime as Date)
AND (s.DateStamp <= ResolvedDateTime OR ResolvedDateTime IS NULL)
GROUP BY d.DateStamp, s.ClientID, s.ContractID, s.ServiceID
Related
I'm trying to retrieve drivers data with Total Accepted and Total Ignored ride requests for the current date.
Based on the Drivers and DriverReceivedRequests tables, I get the total count but the twists is I have duplicate rows that reside on the DriverReceivedRequest table against the driverId and the rideId. So there has to be group by clause on both the driverId and RideId, having the driver getting multiple requests for the current date, but also receiving twice or thrice request for the same ride as well.
This is the table structure for DriverReceivedRequests:
Id DriverId RideId ReceivedStatusId DateTime
------------------------------------------------------------------------
0014d26b 93665f55 fef6fb96 NULL 04:55.6
00175c65 6e62a94e cb214a84 NULL 09:32.1
0017c22b ec9e1297 4b47dc8a 4211357D 10:28:5
0014d26b 6e62a94e fef6fb96 NULL 04:56.8
This is the query I have tried:
select
d.Id, d.FirstName, d.LastName,
Sum(case when drrs.Number = 1 then 1 else 0 end) as TotalAccepted,
Sum(case when drrs.Number = 2 or drr.ReceivedStatusId is null then 1 else 0 end) as TotalRejected
from
dbo.[DriverReceivedRequests] drr
inner join
dbo.[Drivers] d on drr.DriverId = d.Id
left join
dbo.[DriverReceivedRequestsStatus] drrs on drr.ReceivedStatusId = drrs.Id
where
Day(drr.Datetime) = Day(getdate())
and month(drr.DateTime) = Month(getdate())
group by
d.FirstName, d.LastName, d.Id
In the above query if I group by with RideId as well, it generates duplicate names of drivers as well with incorrect data. I've also applied partition by clause with DriverId but not the correct result
This also generates the same result
WITH cte AS
(
SELECT
d.Id,
d.FirstName, d.LastName,
TotalAccepted = SUM (CASE WHEN drrs.Number = 1 THEN 1 ELSE 0 END) OVER (PARTITION BY drr.DriverId),
TotalRejected = SUM (CASE WHEN drrs.Number = 2 OR drr.ReceivedStatusId IS NULL THEN 1 ELSE 0 END)
OVER (PARTITION BY drr.DriverId),
rn = ROW_NUMBER() OVER(PARTITION BY drr.DriverId
ORDER BY drr.DateTime DESC)
FROM
DriverReceivedRequests drr
INNER JOIN
dbo.[Drivers] d ON drr.DriverId = d.Id
LEFT JOIN
dbo.[DriverReceivedRequestsStatus] drrs ON drr.ReceivedStatusId = drrs.Id
WHERE
DAY (drr.Datetime) = DAY (GETDATE())
AND MONTH (drr.DateTime) = MONTH (GETDATE())
)
SELECT
Id,
FirstName, LastName,
TotalAccepted, TotalRejected
FROM
cte
WHERE
rn = 1
My question is how can I group by individual driver data in terms of incoming ride requests?
Note: the driver receives same ride request multiple times
I don't know exactly where I'm wrong, but I need a list of all the workers who are currently at work (for the current day), this is my sql query:
SELECT
zp.ID,
zp.USER_ID,
zp.Arrive,
zp.Deppart,
zp.DATUM
FROM time_recording as zp
INNER JOIN personal AS a on zp.USER_ID, = zp.USER_ID,
WHERE zp.Arrive IS NOT NULL
AND zp.Deppart IS NULL
AND zp.DATUM = convert(date, getdate())
ORDER BY zp.ID DESC
this is what the data looks like with my query:
For me the question is, how can I correct my query so that I only get the last Arrive time for the current day for each user?
In this case to get only these values:
Try this below script using ROW_NUMBER as below-
SELECT * FROM
(
SELECT zp.ID, zp.USER_ID, zp.Arrive, zp.Deppart, zp.DATUM,
ROW_NMBER() OVER(PARTITION BY zp.User_id ORDER BY zp.Arrive DESC) RN
FROM time_recording as zp
INNER JOIN personal AS a
on zp.USER_ID = zp.USER_ID
-- You need to adjust above join relation as both goes to same table
-- In addition, as you are selecting nothing from table personal, you can drop the total JOIN part
WHERE zp.Arrive IS NOT NULL
AND zp.Deppart IS NULL
AND zp.DATUM = convert(date, getdate())
)A
WHERE RN =1
you can try this:
SELECT DISTINCT
USER_ID,
LAR.LastArrive
FROM time_recording as tr
CROSS APPLY (
SELECT
MAX(Arrive) as LastArrive
FROM time_recording as ta
WHERE
tr.USER_ID = ta.USER_ID AND
ta.Arrive IS NOT NULL
) as LAR
I am working on a project for an organisation which handles tickets. I am doing this with SQL Management Studio. They want to know how much time they spend for each customer per month. What I have at the moment is individual tickets for each customer. Somehow I need to add these values by month an show in seperate column.
The column EndTime has the total time spend for each ticket, now I want to add these values for each month.
SELECT
[dbo].[Company].Name as CompanyName
, convert(time(0), CAST(EndTime AS TIME)) AS 'Worked hours'
,EndTime
,Category.Name as CategoryName
FROM [plugin.tickets].[Ticket]
LEFT JOIN [dbo].Category ON Category.Id = [plugin.tickets].Ticket.CategoryId
LEFT JOIN [plugin.tickets].TicketActivity ON TicketActivity.TicketId = [plugin.tickets].Ticket.Id
LEFT JOIN [dbo].Activity ON Activity.Id = [TicketActivity].ActivityId
LEFT JOIN [dbo].Company ON Company.Id = [plugin.tickets].Ticket.CompanyId
where
[plugin.tickets].[Ticket].status <= 2
AND [plugin.tickets].[Ticket].TypeId = 6 or [plugin.tickets].[Ticket].TypeId = 11
AND [dbo].Category.Name != 'VoIP Telefoni' AND [dbo].Category.Name != 'Beheer'
-- AND [dbo].Activity.EndTime is not null
-- AND DATEDIFF(MINUTE, CAST('00:00:00' AS TIME), CAST(EndTime AS TIME)) > 0
GROUP BY
[dbo].[Company].Name
,EndTime
,EndTime
,Category.Name
ORDER BY
'Worked hours' desc
I'm stuck on a query where I am trying to get information on just customers that are newly acquired during a certain date range.
I had need to get a list of customers who placed their first order (of all time) in the first 6 months of the year. I then need to get total of their invoices, first invoice date, last invoice date, and count of orders for just the last 6 months.
I used a HAVING clause to ensure that I am just looking at customers that placed their first order in that 6 month period, but since we are past that period now, the total invoice info and order count information would include orders placed after this time. I considered including a restriction in the HAVING clause for the 'last invoice date', but then I am eliminating customers whose first order date was in the 6 month block, but also ordered after that. I'm not sure what to do next and am not having luck finding similar questions. Here is what I have so far:
SELECT c.customer, MAX(c.name) AS Name,
SUM(
CASE WHEN im.debit = 0
THEN im.amount * -1
ELSE im.amount
END
) AS TotalInvoiceAmount,
MIN(
im.date) AS FirstInvoiceDate,
MAX(
im.date) AS LastInvoiceDate,
COUNT(DISTINCT om.[order]) AS OrderCount
FROM invoicem im
INNER JOIN customer c ON im.customer = c.customer
FULL JOIN orderm om ON im.customer = om.customer
WHERE im.amount <> 0
GROUP BY c.customer
HAVING MIN(im.date) BETWEEN '01-01-2015' AND '06-30-2015'
ORDER BY c.customer
You can put the first 6 months qualification as a subquery. This would also work as a CTE
declare #startDate date = dateadd(month,-6,getdate())
SELECT c.customer, MAX(c.name) AS Name,
SUM(
CASE WHEN im.debit = 0
THEN im.amount * -1
ELSE im.amount
END
) AS TotalInvoiceAmount,
MIN(
im.date) AS FirstInvoiceDate,
MAX(
im.date) AS LastInvoiceDate,
COUNT(DISTINCT om.[order]) AS OrderCount
FROM invoice im
INNER JOIN (SELECT customer from invoice
GROUP BY customer
HAVING MIN(date) BETWEEN '01-01-2015'
AND '06-30-2015') im2
ON im.customer = im2.customer
INNER JOIN customer c ON im.customer = c.customer
FULL JOIN orderm om ON im.customer = om.customer
WHERE im.amount <> 0
AND im.date >= #startdate
GROUP BY c.customer
ORDER BY c.customer
I am working on an time attendance system. I have to following tables:
Schedule: Contains a Name nvarchar field and a Start and End DateTime fields.
Policy: Contains Start and End DateTime fields too.
PolicySchedule (Cross Table): Contains a Priority int field beside the foreign keys.
End datetime fields are nullable which indicates open periods.
The schedule of the greatest priority will be applied and activated within its time and the policy time.
I need to get a list of the applied schedules within each policy and their activation periods start and end time knowing that shedules may be intersected. Policies are not related here ..
Example:
Schedule_____________Start_________________________End
Schedule1____________01/01/2011 00:00______________04/01/2011 00:00
Schedule2____________04/01/2011 00:00______________11/01/2011 14:00
Schedule3____________11/01/2011 14:00______________02/15/2012 00:00
Schedule2____________02/15/2012 00:00______________01/01/2013 00:00
What is the most efficient way to get the requested result ?
If you have lots of policies and schedules (separately) but few schedules per policy, the most straightforward way would be quite efficient:
WITH dates (policyId, changeDate) AS
(
SELECT policyId, changeDate,
ROW_NUMBER() OVER (PARTITION BY policyId ORDER BY changeDate) AS rn
FROM (
SELECT policyId, startDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
UNION
SELECT policyId, endDate AS changeDate
FROM policySchedule ps
JOIN schedule s
ON s.id = ps.scheduleId
) q
),
ranges (startDate, endDate)AS
(
SELECT d1.policyId,
d1.changeDate,
d2.changeDate
FROM dates d1
JOIN dates d2
ON d2.policyId = d1.policyId
AND d2.rn = d1.rn + 1
)
SELECT *
FROM policy p
JOIN ranges r
ON r.policyId = p.id
CROSS APPLY
(
SELECT TOP 1 s.*
FROM policySchedules ps
JOIN schedule s
ON ps.policyId = p.id
AND s.id = ps.scheduleId
WHERE ps.startDate BETWEEN r.startDate AND r.endDate
AND ps.endDate BETWEEN r.startDate AND r.endDate
ORDER BY
ps.Priority DESC
)
Assuming you're using SQL Server 2005 or later, you can use an outer apply to look up the policy with the highest priority:
select *
from Schedule s
outer apply
(
select top 1 *
from PolicySchedule ps
join Policy p
on p.id = ps.policyid
where s.StartTime <= p.EndTime
and p.StartTime <= s.EndTime
order by
ps.priority desc
) pol
If there are time periods that have to overlap, you can add a where clause in the outer apply.