Query to find late parts shipped and list them by quarter - sql

I am having the toughest time getting a query created for this scenario:
I need to list all parts that were late and sum them by quarter.
Here is the query that I have so far:
SELECT DISTINCTROW
Format$([InvoiceSub].[Date_Shipped],'\Qq yyyy') AS [Date_Shipped By Quarter]
, Sum(InvoiceSub.Quantity) AS [Sum Of Quantity]
FROM
InvoiceSub
INNER JOIN
Job_Book_Sub
ON (InvoiceSub.[Job #] = Job_Book_Sub.[Job #])
AND (InvoiceSub.[LineItem#] = Job_Book_Sub.[LineItem#])
GROUP BY
Format$([InvoiceSub].[Date_Shipped],'\Qq yyyy')
, Year([InvoiceSub].[Date_Shipped]) * 4 + DatePart('q', [InvoiceSub].[Date_Shipped]) -1;
This query works fine to display all parts that were shipped by quarter. However, I want to see all parts that were shipped LATE by quarter.
I have a field in a table named: Job_Book_Sub, and that field is [LineItem_DueDate]. I want to use that in the query so that it will display all parts that were late ([date_shipped] > [lineitem_duedate]). The [date_shipped] is the actual date the parts were shipped, [lineitem_duedate] is the date the parts were due. I know that I need to incorporate these two fields into the query, I just don't know how.
Can someone please show me how to do this? If I add the [LineItem_DueDate] to the query, then it no longer sums the dates by quarter but instead lists every record (so instead of having 45 records with different quarters over the past 10+ years, I all of a sudden have 13000+ records because it is listing each record with date_shipped in the query.
Can someone help please?

Try adding your filter in a WHERE clause:
SELECT DISTINCTROW
Format$([InvoiceSub].[Date_Shipped],'\Qq yyyy') AS [Date_Shipped By Quarter]
, Sum(InvoiceSub.Quantity) AS [Sum Of Quantity]
FROM
InvoiceSub
INNER JOIN
Job_Book_Sub
ON (InvoiceSub.[Job #] = Job_Book_Sub.[Job #])
AND (InvoiceSub.[LineItem#] = Job_Book_Sub.[LineItem#])
WHERE
Job_Book_Sub.[date_shipped] > Job_Book_Sub.[lineitem_duedate]
GROUP BY
Format$([InvoiceSub].[Date_Shipped],'\Qq yyyy')
, Year([InvoiceSub].[Date_Shipped]) * 4 + DatePart('q', [InvoiceSub].[Date_Shipped]) -1;

Related

How to find if there is a match in a certain time interval between two different date fields SQL?

I have a column in my fact table that defines whether a Supplier is old or new based on the following case-statement:
CASE
WHEN (SUBSTRING([Reg date], 1, 6) = SUBSTRING([Invoice date], 1, 6)
THEN ('New supplier')
ELSE('Old supplier')
END as [Old/New supplier]
So for example, if a Supplier was registered 201910 and Invoice date was 201910 then the Supplier would be considered a 'New supplier' that month. Now I want to calculate the number of Old/New suppliers for each month by doing an distinct count on Supplier no, which is not a problem. The last step is where it gets tricky, now I want to count the number of New/Old suppliers over a 12-month period(if there has been a match on Invoice date and reg date in any of the lagging 12 months). So I create the following mdx expression:
aggregate(parallelperiod([D Time].[Year-Month-Day].[Year],1,[D Time].[Year-Month-Day].currentmember).lead(1) : [D Time].[Year-Month-Day].currentmember ,[Measures].[Supplier No Distinct Count])
The issue I am facing is that it will count Supplier no "1234" twice since it has been both new and old during that time period. What I wish is that, if it finds one match it would be considered a "New" Supplier for that 12- month period.
This is how the result ends up looking but I want it to be zero for "Old" since Reg date and Invoice date matched once during that 12-month period it should be considered new for the whole Rolling 12 month on 201910
Any help, possible approaches or ideas are highly appreciated.
Best regards,
Rubrix
Aggregate first at the supplier level and then at the type level:
select type, count(*)
from (select supplierid,
(case when min(substring(regdate, 1, 6)) = min(substring(invoicedate, 1, 6))
then 'new' else 'old'
end) as type
from t
group by supplierid
) s
group by type;
Note: I assume your date columns are in some obscure string format for your code to work. Otherwise, you should be using appropriate date functions.
SELECT COUNT(*) OVER () AS TotalCount
FROM Facts
WHERE Regdate BETWEEN(olddate, newdate) OR InvoiceDate BETWEEN(olddate, newdate)
GROUP BY
Supplier
The above query will return all the suppliers within that time period and then group them. Thus COUNT(*) will only include unique subscribers.
You might wanna change the WHERE clause because I didn't quite understand how you are getting the 12 month period. Generally if your where clause returns the suppliers within that time period(they don't have to be unique) then the group by and count will handle the rest.

SQL case expression to run report based on Fiscal Year

I'm attempting to create some reports in my organization's new Help Desk system, which uses sql for its database and reporting systems. I've never interacted with sql before, so I'm having to make this up as I go. I've been able to cannibalize most of what I need from other, pre-made reports, but I'm running into a road block getting the report to group by Fiscal Year and not Calendar Year. The report I'm currently working on is meant to calculate the average time to closure on tickets. The original version grouped and ordered everything by the calendar year, and appeared to be working. However, when I try to retrofit the code to group/sort based on a July 1-June 30 Fiscal Year using the suggested method in this answer (as shown in my report code below), I'm getting the error, "The multi-part identifier "htblticket.date could not be bound."
I also tried some variants on this answer, with even less success. Does anyone have some suggestions on what I might be screwing up here, or some ideas on better ways to approach this? I'd appreciate any help/enlightenment you can provide!
Select Top 1000000 Case
When DatePart(mm, htblticket.date) > 6 Then DatePart(yyyy, htblticket.date)
+ 1
Else DatePart(yyyy, htlbticket.date)
End As [Fiscal Year],
Convert(Decimal(9,2),Avg(Cast(DateDiff(ss, htblticket.date,
ClosedDate.CloseDate) As decimal) / 86400)) As AverageDays
From htblticket
Inner Join (Select Top 1000000 htblticket.ticketid,
Max(htblhistory.date) As CloseDate
From htblticket
Inner Join htblticketstates On htblticketstates.ticketstateid =
htblticket.ticketstateid
Inner Join htblhistory On htblhistory.ticketid = htblticket.ticketid
Inner Join htblticketstates htblticketstates1 On
htblhistory.ticketstateid = htblticketstates1.ticketstateid
Inner Join htblhistorytypes On htblhistorytypes.typeid =
htblhistory.typeid
Where htblticketstates.statename = 'Closed' And
htblticketstates1.statename = 'Closed' And
htblhistorytypes.name In ('Status changed',
'Note added and state changed', 'Internal note added and state changed')
Group By htblticket.ticketid) As ClosedDate On ClosedDate.ticketid =
htblticket.ticketid
Group By Case
When DatePart(mm, htblticket.date) > 6 Then DatePart(yyyy, htblticket.date)
+ 1
Else DatePart(yyyy, htlbticket.date)
End
Order By [Fiscal Year] Desc
Your question boils down to how to group by the (Australian) financial year July-June.
One simple approach would be to create a column “financial_year_start” which is an expression that subtracts 6 months from each date and extracts the year of the result, then group by that.

How to group totals

I am trying to group by category - But the SQL I am using is grouping them all by date.
Example:
If a user selects a date range of 01/04/17 - 20/04/17 it will show them total number found under category A
Whats actually happening:
The results are showing Category A 10 times and showing me the total number of each date rather than a complete grouped total
Hope this makes sense
SELECT tbl_ComplaintsCoded.CauseManager, Count(tbl_ComplaintsCoded.CauseManager) AS CountOfCauseManager, tbl_ComplaintsCoded.[Account Number], tbl_ComplaintsCoded.TouchCSM, tbl_ComplaintsCoded.[Mail Date]
FROM tbl_ComplaintsCoded
GROUP BY tbl_ComplaintsCoded.CauseManager, tbl_ComplaintsCoded.[Account Number], tbl_ComplaintsCoded.TouchCSM, tbl_ComplaintsCoded.[Mail Date]
HAVING (((tbl_ComplaintsCoded.TouchCSM)=[Forms]![frm_Central_Reporting]![Combo209]) AND ((tbl_ComplaintsCoded.[Mail Date]) Between [Forms]![frm_Central_Reporting]![Text204] And [Forms]![frm_Central_Reporting]![Text206]));
this should get what you want:
SELECT tbl_ComplaintsCoded.CauseManager, Count(tbl_ComplaintsCoded.CauseManager) AS CountOfCauseManager, tbl_ComplaintsCoded.[Account Number], tbl_ComplaintsCoded.TouchCSM, tbl_ComplaintsCoded.[Mail Date]
FROM tbl_ComplaintsCoded
WHERE tbl_ComplaintsCoded.TouchCSM = [Forms]![frm_Central_Reporting]![Combo209]
AND (tbl_ComplaintsCoded.[Mail Date] BETWEEN [Forms]![frm_Central_Reporting]![Text204] AND [Forms]![frm_Central_Reporting]![Text206])
GROUP BY tbl_ComplaintsCoded.CauseManager
HAVING CountOfCauseManager > 0;
Also, please read: WHERE vs HAVING

calculating month salary for an employee

I am working on my Database in MS Access 2010
and i Need to build a query to Calculate the month salary for each Employee
it goes like this :
Input from user , which Year
Input from user again , which Month
Show Every Employee's Salary for the Input date
There are 2 Tables in the Query : Shifts , Employees
Shifts has a field for EmployeeID and a field for Day
Day field format is : Short Date
The problem is i don't know how to access the Month and the Year only !
I know that this is completely wrong , but i wanna do something like this:
SELECT
FROM EmployeesTBL INNER JOIN ShiftsTBL ON EmployeesTBL.EmployeeID = ShiftsTBL.EmployeeID
WHERE
Year(ShiftsTBL.Day)=[Enter Year]
AND
Month(ShiftsTBL.Day)=[Enter Month]
;
What do i need to write after SELECT to get the Sum of all Shifts and divide it by number of days the emp worked
Note : in the Shifts Table , i have EntryDate and ExitDate for every shift
Access has a bunch of built in date functions. I believe Month(date) and Year(date) will give you what you need.
Something like
SELECT EmpName
FROM Employees, Shifts
WHERE Employees.EmployeeID = Shifts.EmployeeID
AND
Month(Shifts.Day) = INPUT2.VALUE
AND
Year(Shifts.Day) = INPUT1.VALUE
should get you what you want!
EDIT: Aggregation: how this works will depend on how your database is set up. I think I understand you want to sum the hours worked and divide by the number of days?
If so, you will use Sum() and Count(). And you will Group By EmployeeID
SELECT Sum(Shifts)/Count(DaysWorked) AS SumDividedByCount
FROM EmployeesTBL INNER JOIN ShiftsTBL
ON EmployeesTBL.EmployeeID = ShiftsTBL.EmployeeID
WHERE
Year(ShiftsTBL.[Day])=[Enter Year]
AND
Month(ShiftsTBL.[Day])=[Enter Month]
GROUP BY EmployeeID
I used the WHERE clause because I think the results need to be filtered before they're grouped. If the results needed to be filtered after they were grouped, the HAVING clause would be used (and would go AFTER the GROUP BY)

SQL Difference Between Current Year and Last Year. If Last Year Data Does Not Exist Include Current Year

In a previous post I got help finding incremental sales. The query works great. I added the breakout by product. The issue I’m having is that I need to show new products being sold. If the product did not exist last year, but we are selling it this year; then it should show up in the data table.
I tried use a CASE statement in the WHERE, but it was causing a lot of duplication of the data. I was thinking something like what is below. How do I go about including items that are only in the current year? Thank you for your help, its greatly appreciated.
Not Working Where Clause
WHERE
Ym.Project =
CASE
WHEN ymprev.Project IS NULL THEN ym.Project
ELSE ymprev.Project
END
Below is the working query.
WITH ym as(
SELECT
Product
,SUM(Sales) AS Sales
,MONTH(Date) AS Month
,YEAR(Date) AS Year
FROM SalesTable
GROUP BY
YEAR(Date)
,MONTH(Date)
,Product
)
SELECT
ymprev.Project AS PrevProject
,ym.Product
,ym.Sales
,ymprev.Sales AS PreviousSales
,(ym.Sales - ymprev.Sales) AS IncrementalSales
,ymprev.Month AS PreviousMonth
,ymprev.Year AS PreviousYear
,ym.Month
,ym.Year
FROM ym
JOIN ym ymprev on
ymprev.Year = ym.Year
AND ymprev.Month = ym.Month
AND ymprev.Product = ym.Product
ORDER BY
ym.Year
,ym.Month
Your query is implicitly using an INNER JOIN - this means that you will only see values that have a match in both datasets, just as you describe.
Try changing your FROM clause to
FROM ym
LEFT JOIN
ym ymprev on
ymprev.Year = ym.Year
AND ymprev.Month = ym.Month
AND ymprev.Product = ym.Product
You will also need to incorporate similar logic in any values that include data elements from the previous year's query. For example, ,(ym.Sales - ymprev.Sales) AS IncrementalSales will need to be turned into ,(ym.Sales - ISNULL(ymprev.Sales,0)) AS IncrementalSales or it will return NULL for any records that only exist in the current year.
Your posted query doesn't include the Project field in your CTE, so I can't tell exactly how that works, but the posted data should get you started.