Look at data in one date range and count from another date range - sql-server

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

Related

SUM datetime value by month

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

Query running tally of open issues on a given day

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

how to use count, case and Distinct together in sql server

I want to create a statement but i not success to complete this. can you please take a look and let me know what i need to do to complete this. My problem due how to add these two part in my query.
I want to look at the last 30 days of orders for each DRV1NUM. If that driver has worked 0 days then say ‘NOT ACTIVE’. If the driver has worked more than 15 days then ‘FULL TIME’ and less than 15 days is ‘PART TIME’.
In this one, I want to look at the last 30 days of orders and compare the left(4) of DRIVERNUM to the entire DRIVERNUM. In some instances, we have drivers where there is a 5th letter after the left 4.I want to look at the last 30 days of orders and if the left(4) DRV1NUM has more than one DRV1NUM WHEN looking at all characters, then SAY ‘MASTER’
SELECT DISTINCT DRVLICNUM,DOB,COUNTRY,CREDITLIMIT,DRIVERNUM=LEFT(DRIVERNUM,4),
SSN,D.VEHICLE,PHN1,DRVLICST,HOST,VEHICLE_MC,
VEHICLE_DOT,BACK_APPROVED=CASE WHEN PROBDATE IS NOT NULL THEN 'YES' ELSE 'NO' END
-- CASE WHEN COUNT(DISTINCT O.DROPDATE)=0 IN LAST 30 DAYS THEN 'NOT ACTIVE' WHEN COUNT(DISTINCT O.DROPDATE)>15 IN LAST 30 DAYS THEN 'FULL TIME' WHEN COUNT(DISTINCT O.DROPDATE)>=1 AND <=15 THEN 'PART TIME' IN LAST 30 DAYS ELSE NULL AS DAYSWORKED,
-- --CASE WHEN COUNT(DISTINCT O.DRV1NUM OF LEFT(DRIVERNUM,4 )>0 IN LAST 30 DAYS OF ORDERS>1 THEN 'MASTER IC' ELSE NULL AS MASTER
/* ABOVE TWO STATEMENT I WANT TO ADD */
FROM DRIVER D
FULL OUTER JOIN orde_ O ON O.DRV1ID=D.DRIVERID
AND ISNUMERIC(DRIVERNUM)=1 and DRIVERNUM NOT IN ('1010')
Expected Output That i want
DRVLICNUM Employee DOB COUNTRY ACTIVESTATUS
---------------------------------------------------------
055243324 CONTRACTOR 1985-04-13 ATLANTA FULL TIME
Here the ActiveStatus is Active because the driver worked more than 15 days in past 15 days or if it will less then 15 days it will be 'Part Time'
I don't have access to google drive link which you shared.
However, you will have to use CTE (common table expression) to get count of days and then use it compute value of ActiveStatus column.
Try using below code:
;
WITH CTE1
AS(
SELECT D.DRIVERID,
COUNT(DISTINCT O.DROPDATE) AS DayCount
FROM DRIVER AS D
LEFT JOIN ORDER AS O ON D.DRIVERID=O.DRV1ID AND O.DROPDATE BETWEEN CONVERT(DATE,DATEADD(DAY,-30,GETDATE())) AND GETDATE()
WHERE ISNUMERIC(D.DRIVERNUM)=1 AND D.DRIVERNUM NOT IN ('1010')
GROUP BY D.DRIVERID
)
SELECT DRVLICNUM,DOB,COUNTRY,CREDITLIMI,...
CASE
WHEN DayCount=0 THEN 'NOT ACTIVE'
WHEN DayCount<=15 THEN 'PART TIME'
WHEN DayCount>=30 THEN 'FULL TIME'
END AS ACTIVESTATUS
FROM CTE1 AS C
JOIN DRIVER AS D ON C.DRIVERID=D.DRIVERID
here is two siple queries for the first one:
1) select order by dates and group by driver (if there no more than one order per day):
select o.DRIVERID
, count(*) as cnt
from orde_ o
where o.DROPDATE betwen GETDATE() AND DATEADD(DAY,-30,GETDATE())
group by o.DRIVERID
2) select drivers and join groupped orders
select case
when o.ctn >= 15 then 'FULL TIME'
when o.ctn > 0 then 'PART TIME'
else 'NOT ACTIVE'
end
, <other fields you want>
from DRIVER as D
left join <query above> as o
on o.DRIVERID = d.DRIVERID
for the second one:
select left(d.DRIVERID, 4), count(*) as cnt
from DRIVER as D
group by left(d.DRIVERID, 4)
having count(*) > 1
and just join it, if is not null then compare whole id's

Exclude certain line depending on a certain condition in t-SQL

Firstly, I have created the following stock sales SELECT statement:
SELECT
PostST.TxDate AS TxDate,
PostST.Reference AS InvNum,
Client.Name AS CustomerName,
SalesRep.Code AS SalesRep,
WhseMst.Code AS Whse,
CONCAT (StkItem.Description_1, ' - ',StkItem.Code) AS Item,
_etblLotTracking.cLotDescription AS LotNumber,
CASE
WHEN PostST.TrCodeID = 34 THEN (PostST.Quantity * 1)
WHEN PostST.TrCodeID = 30 THEN (PostST.Quantity * -1)
ELSE 0
END AS QtySold,
CAST
(
CASE
WHEN PostST.TrCodeID = 34 THEN (PostST.Credit / PostST.Quantity)
WHEN PostST.TrCodeID = 30 THEN (PostST.Debit / (PostST.Quantity * -1))
ELSE 0
END
as [money]
)
AS CustomerPrice,
StkItem.ItemGroup AS ItemGroup,
StkItem.ulIIStockType AS StockType,
YEAR (PostST.TxDate) AS Year,
DATENAME (MONTH, (PostST.TxDate)) AS Month
FROM
PostST
INNER JOIN StkItem
ON StkItem.StockLink = PostST.AccountLink
INNER JOIN PostAR
ON PostAR.cAuditNumber = PostST.cAuditNumber
INNER JOIN Client
ON Client.DCLink = PostAR.AccountLink
INNER JOIN SalesRep
ON SalesRep.idSalesRep = PostAR.RepID
INNER JOIN WhseMst
ON WhseMst.WhseLink = PostST.WarehouseID
FULL JOIN _etblLotTracking
ON _etblLotTracking.idLotTracking = PostST.iLotID
WHERE
PostST.TrCodeID IN (34, 30) AND StkItem.ItemGroup <> 'TRAN'
This query is run from Sage Evolution and data is dumped into Excel. From there I manipulate to view each item and the sales history in quantity per month and year.
My problem is as follows:
Within the data that follows, is sometimes a customer who has perhaps stopped buying a particular item. What I need is for this statement to also filter out a line by the following condition:
If the customer does not have a sale for 6 months or more, then that STOCK ITEM must be filtered out for that specific customer.
Thank you!

Counting duplicate items in different order

Goal:
To know if we have purchased duplicate StockCodes or Stock Description more than once on difference purchase orders
So, if we purchase Part ABC on Purchase Order 1 and Purchase Order 2, it should return the result of
PurchaseOrders, Part#, Qty
Purchase Order1, Purchase Order2, ABC, 2
I just don't know how to pull the whole code together, more to the point, how do I know if it's occurred on more than 1 Purchase Order without scrolling through all the results , may also have to do with Multiple (Having Count) Statements as I only seem to be doing by StockCode
SELECT t1.PurchaseOrder,
t1.MStockCode,
Count(t1.MStockCode) AS SCCount,
t1.MStockDes,
Count(t1.MStockDes) AS DescCount
FROM PorMasterDetail t1
INNER JOIN PorMasterHdr t2
ON t1.PurchaseOrder = t2.PurchaseOrder
WHERE Year(t2.OrderEntryDate) = Year(Getdate())
AND Month(t2.OrderEntryDate) = Month(Getdate())
GROUP BY t1.PurchaseOrder,
t1.MStockCode,
t1.MStockDes
HAVING Count(t1.MStockCode) > 1
Using responses I came up with the following
select * from
(
SELECT COUNT(dbo.InvMaster.StockCode) AS Count, dbo.InvMaster.StockCode AS StockCodes,
dbo.PorMasterDetail.PurchaseOrder, dbo.PorMasterHdr.OrderEntryDate
FROM dbo.InvMaster INNER JOIN dbo.PorMasterDetail ON
dbo.InvMaster.StockCode = dbo.PorMasterDetail.MStockCode
INNER JOIN dbo.PorMasterHdr ON dbo.PorMasterDetail.PurchaseOrder = dbo.PorMasterHdr.PurchaseOrder
WHERE YEAR(dbo.PorMasterHdr.OrderEntryDate) = YEAR(GETDATE())
GROUP BY dbo.InvMaster.StockCode, dbo.InvMaster.StockCode,
dbo.PorMasterDetail.PurchaseOrder, dbo.PorMasterHdr.OrderEntryDate
) Count
Where Count.Count > 1
This returns the below , which is starting to be a bit more helpful
In result line 2,3,4 we can see the same stock code (*30044) ordered 3 times on different
purchase orders.
I guess the question is, is it possible to look at If something was ordered more than once within say a 30 day period.
Is this possible?
Count StockCodes PurchaseOrder OrderEntryDate
2 *12.0301.0021 322959 2014-09-08
2 *30044 320559 2014-01-21
8 *30044 321216 2014-03-26
4 *30044 321648 2014-05-08
5 *32317 321216 2014-03-26
4 *4F-130049/TEST 323353 2014-10-22
5 *650-1157/E 322112 2014-06-24
2 *650-1757 321226 2014-03-27
SELECT *
FROM
(
SELECT h.OrderEntryDate, d.*,
COUNT(*) OVER (PARTITION BY d.MStockCode) DupeCount
FROM
PorMasterHdr h
INNER JOIN PorMasterDetail d ON
d.PurchaseOrder = h.PurchaseOrder
WHERE
-- first day of current month
-- http://blog.sqlauthority.com/2007/05/13/sql-server-query-to-find-first-and-last-day-of-current-month/
h.OrderEntryDate >= CONVERT(VARCHAR(25), DATEADD(dd,-(DAY(GETDATE())-1),GETDATE()),101)
) dupes
WHERE
dupes.DupeCount > 1;
This should work if you're only deduping on stock code. I was a little unclear if you wanted to dedupe on both stock code and stock desc, or either stock code or stock desc.
Also I was unclear on your return columns because it almost looks like you're wanting to pivot the columns so that both purchase order numbers appear on the same line.

Resources