Query to get Daywise on the month selected - sql

I have an MS Access database table datetime column. When I select a particular month (say, July), I have to get datewise data in that month.
The output should appear in the same format as the attached image.
Every Employee who comes in on a particular date should display “P” for that day. If the Employee doesn’t come in on a particular day (like Sat or Sun), then I have to display “WO” for that day.
When an Employee has not come in (like Sat or Sun), then there is no entry in the log table for that date.
How could an Access query be written to obtain this output? I am using an MS Access 2003 database.
Edit: we have to use TRANSFORM and PIVOT, but the issue is when an employee is not available (Sat, Sun) we still need to show data in the output.

Set up a query that reads EmpID and CheckTime from the first table, and adds one additional column:
DateWise: IIf(Weekday([CheckTime])=1 Or Weekday([CheckTime])=7,"WO","P")
You will need an additional table with every date of the year in it (we'll call it YearDates). Left join that table to your query like so:
Select YD.YearDates, Q2.* from YearDates YD LEFT JOIN Query2 Q2 ON YD.YearDates = DATEVALUE(Q2.CheckTime)
The DATEVALUE will strip the time off your dates in CheckTime so they will match date against date.

Related

Running an Access query on a FILTERED table

I have some related tables that I want to run a Totals/Group By query on.
My "Tickets" table has a field called "PickDate" which is the date that the order/ticket was fulfilled.
I want to group by the weekday (name) (a calculated field) so that results for certain customers on the same day of the week are grouped. Then the average ticket completion time can be calculated per customer for each weekday. It would look something like the following.
--CustName---Day---AvTime
Customer 1 - MON - 72.3
- TUE - 84.2
- WED - 110.66
..etc
..etc
..etc
Customer 2 ..
This works fine but the problem I am having is that when this query is run, it works on every record from the tickets table. There are some reasons that, for certain reports, the data that it the query is referencing should be restricted between a date range; for example to track a change in duration over a number of weeks.
In the query properties, there is a property, "filter", to which I can add a string such as:
"([qryCustomerDetails].[PickDate] Between #11/1/2021# And #11/14/2021#)"
to filter the results. The only issue is that since each date is unique, the "group by" of like days such as "Monday" is overridden by this unique date "11/1/2021". The query only works when the PickDate is removed as a field. However, then I can't access it to filter by it.
What I want to achieve would be the same as; in the "Tickets" table itself filtering the results between two dates and then having a query that could run on that filtered table.
Is there any way that I could achieve this?
For reference here is the SQL of the query.
FROM tblCustomers INNER JOIN tblTickets ON tblCustomers.CustomerID = tblTickets.CustomerID
GROUP BY tblCustomers.Customer, WeekdayName(Weekday([PickDate]),False,1), tblCustomers.Round, Weekday([PickDate])
ORDER BY tblCustomers.Round, Weekday([PickDate]);
You probably encountered two issues. The first issue is that to filter results in a totals query by un totaled fields you use HAVING rather than WHERE. the second issue is that calculated fields like Day don't exist at the time of the query. You can't say having Day > Mon. Instead you must repeat the calculation of Day: Having CalculateDay(PickDate) > Monday
The designer will usually figure out whether you want having or where automatically. So here is my example:
this gives you the SQL:
SELECT Tickets.Customer, WeekdayName(Weekday([PickDate])) AS [Day], Avg(Tickets.Time) AS AvTime
FROM Tickets
GROUP BY Tickets.Customer, WeekdayName(Weekday([PickDate])), Tickets.PickDate
HAVING (((Tickets.PickDate) Between #11/16/2021# And #11/17/2021#))
ORDER BY Tickets.PickDate;

SQL query for percentage change compared to previous date

I have a table within access containing the performance of departments on different reference dates. All data is within one table "tblmain". The table contains the following fields:
reference date (called "ref_date", formatted dd.mm.yyyy)
department identifier (called "dep_id")
performance value (called "val")
Every reference date consists of round about 100 departments and every week I import a new reference date.
My goal now is to build a query which calculates the percentage change from on reference date compared to the previous reference date. Furthermore, it should only show the departments with a change bigger than 5%.
I am currently stuck. I have created a query that gives me the val from the previous reference date but only for one specific department. And I do not know how to continue. This query looks as follows:
SELECT TOP 1 tblmain.val
FROM (SELECT TOP 2 tblmain.val, tblmain.ref_date FROM tblmain WHERE dep_id=1 ORDER BY tblmain.ref_date DESC)
ORDER BY tblmain.ref_date;
I would appreciate any feedback. After finishing this query, I plan to use this query in a form where I can choose an reference date and threshold.
Many thanks in advance!
Query to pull prior val for each record:
SELECT tblMain.ID, tblMain.ref_date, tblMain.dep_id, tblMain.val,
(SELECT TOP 1 val FROM tblMain AS Dupe
WHERE Dupe.dep_id=tblMain.dep_id AND Dupe.ref_Date < tblMain.ref_date
ORDER BY dupe.ref_date) AS PriorVal
FROM tblMain;
Now use that query to calculate percentage:
SELECT Query1.*, Abs(([PriorVal]-[val])/[PriorVal]*100) AS P
FROM Query1
WHERE (((Abs(([PriorVal]-[val])/[PriorVal]*100))>5));

How to get records month wise on rollover calender

I am using following query to get records count on month wise and it is working fine:
SELECT MONTH(dte_cycle_count) MONTH, COUNT(*) COUNT
FROM inventory
WHERE YEAR(dte_cycle_count)='2021' --OR (MONTH(dte_cycle_count) = '1' OR MONTH(dte_cycle_count) = '12')
GROUP BY MONTH(dte_cycle_count);
Problem:
Now I need to bind rollover calendar so user can scroll or click on next or previous button the next 12 Months record will be visible.
eg. Current month is MARCH, So default records will be from APR2020 to MARCH2021. If user click on previous then records will come MAR2020 to FEB2021.
How I can achieve this?
Please let me know if need more information. I will try my best to provide.
I think what you are after is a date list from which to join to your inventory table.
Like a numbers table, build a static table with columns for date, year, month, populated from whenever you need to far in the future.
You then select from this, applying your filtering range critera, and join to your inventory table.
For an efficient query, ideally your inventory table should have the relevant date portions eg year and month stored to match.
You don't want to be using functions on a datetime to extract the year or month as this is not sargable and will not allow any index to be used for a seek lookup.

Average calls per day in MS Access 2010

I'm a receptionist keeping track of incoming calls in MS-Access 2010. The table has Date column. I can get count of calls per day but am having trouble with SQL to get average calls per day.
Assuming your table has one record per call, you can use a query like this, just replace the table and field names:
SELECT Avg(TotalCalls.DailyCalls) AS AverageCalls
FROM
(
SELECT MyTable.MyDateField, Count(MyTable.MyDateField) AS DailyCalls
FROM MyTable
WHERE MyDate > #1-Feb-2017# AND MyDate <= #28-Feb-2017#
GROUP BY MyTable.MyDateField
) AS TotalCalls
This won't take into account days that have no calls, just the ones that do. The WHERE clause is optional, but you might want to use that to pick a specific date range.

GROUP BY with date range

I have a table with 4 columns, id, Stream which is text, Duration (int), and Timestamp (datetime). There is a row inserted for every time someone plays a specific audio stream on my website. Stream is the name, and Duration is the time in seconds that they are listening. I am currently using the following query to figure up total listen hours for each week in a year:
SELECT YEARWEEK(`Timestamp`), (SUM(`Duration`)/60/60) FROM logs_main
WHERE `Stream`="asdf" GROUP BY YEARWEEK(`Timestamp`);
This does what I expect... presenting a total of listen time for each week in the year that there is data.
However, I would like to build a query where I have a result row for weeks that there may not be any data. For example, if the 26th week of 2006 has no rows that fall within that week, then I would like the SUM result to be 0.
Is it possible to do this? Maybe via a JOIN over a date range somehow?
The tried an true old school solution is to set up another table with a bunch of date ranges that you can outer join with for the grouping (as in the other table would have all of the weeks in it with a begin / end date).
In this case, you could just get by with a table full of the values from YEARWEEK:
201100
201101
201102
201103
201104
And here is a sketch of a sql statement:
SELECT year_weeks.yearweek , (SUM(`Duration`)/60/60)
FROM year_weeks LEFT OUTER JOIN logs_main
ON year_weeks.yearweek = logs_main.YEARWEEK(`Timestamp`)
WHERE `Stream`="asdf" GROUP BY year_weeks.yearweek;
Here is a suggestion. might not be exactly what you are looking for.
But say you had a simple table with one column [year_week] that contained the values of 1, 2, 3, 4... 52
You could then theoretically:
SELECT
A.year_week,
(SELECT SUM('Duration')/60/00) FROM logs_main WHERE
stream = 'asdf' AND YEARWEEK('TimeStamp') = A.year_week GROUP BY YEARWEEK('TimeStamp'))
FROM
tblYearWeeks A
this obviously needs some tweaking... i've done several similar queries in other projects and this works well enough depending on the situation.
If your looking for a one table/sql based solution then that is deffinately something I would be interested in as well!