Counting/grouping records in Access query - ms-access

I encountered an issue while trying to group records in a query.
What I need is - after I select DatePeriod from a comboBox - in an underlying subform to have a count of records for each employee within selected date period.
Overview
Note: for simplicity, I used two fields only.
Main Form has TabControl. Each Tab has a subform (Source: query). Each record in a query has Date (V_LOCATION_VISIT_DATE) and Employee (V_WORKER) fields. Each V_WORKER has hundreds of entries (link to Oracle db).
On a form I have cboDatePeriod (example: „16.05.2018-15.06.2018“).
After selecting a value from a cboDatePeriod, a code compares DatePeriod with dates in a queries and filters it.
A query has INNER JOIN to qryEmployees, since I want to count records for specific Employees.
Example of entries in a table DATA:
|V_WORKER | V_LOCATION_VISIT_DATE
| David Sylvian | 08.01.2018 14:38:21
| David Sylvian | 08.01.2018 15:31:48
| David Sylvian | 08.01.2018 16:22:07
| Brian Eno | 08.01.2018 17:33:07
| Brian Eno | 09.01.2018 16:18:50
| Brian Eno | 09.01.2018 17:09:21
Code without date:
SELECT qryDATA.V_WORKER,Count(qryDATA.V_WORKER) AS CountOfV_WORKER
FROM qryEmployeesCZS DATA ON qryEmployeesCZS.FullName = qryDATA.V_WORKER
GROUP BY qryDATA.V_WORKER
HAVING (((qryDATA.V_WORKER)<>""));
Query result example:
|V_WORKER | CountOfV_WORKER
| David Sylvian | 821
| Brian Eno | 92
It's how it should look alike, after applying DatePeriod filter. Let's move on.
Code with date included:
With Date included int function to remove Time stamp) instead having a single record for each Employee I have many records for each Employee, where each record is a count of records for a single day (grouped by V_WORKER and DAY).
SELECT qryDATA.V_WORKER, Int([qryDATA].[V_LOCATION_VISIT_DATE]) AS V_LOCATION_VISIT_DATE,
Count(qryDATA.V_WORKER) AS CountOfV_WORKER
FROM DATA
INNER JOIN qryEmployeesCZS ON qryDATA.V_WORKER = qryEmployeesCZS.[FullName]
GROUP BY qryDATA.V_WORKER,Int([DATA].[V_LOCATION_VISIT_DATE])
HAVING (((qryDATA.V_WORKER)<>""));
Query result example (I used int function to remove timestamp):
| V_WORKER | V_LOCATION_VISIT_DATE | CountOfV_WORKER
| David Sylvian | 08.01.2018 | 4
| David Sylvian | 09.01.2018 | 6
| David Sylvian | 10.01.2018 | 2
| Brian Eno | 11.01.2018 | 4
| Brian Eno | 12.01.2018 | 2
| Brian Eno | 15.01.2018 | 5
| Brian Eno | 16.01.2018 | 3
What I want:
After selecting Date period from a comboBox, I want to count a records grouped by V_WORKER - it should look like this:
| V_WORKER- | CountOfV_WORKER
| David Sylvian | 26
| Brian Eno | 17
I tried with a Textbox in a subform which counts records, but of course it counts all records, not grouped by employee.
What I'm thinking of (in a moment of desperation) to have two queries in a subform: queryOne will have all records with dates and no grouping, and a second one (source: queryOne) with removed Date field and grouping included.
Any ideas?

This is how aggregation and GROUP BY work.
If you group by date, you will get the count per date.
If you want to only group by employee to get the full count, then do that. Remove V_LOCATION_VISIT_DATE from the GROUP BY clause.
Which date would you want to get with the full count? The first? The last? Then use MIN() or MAX() aggregate functions for the date.
Edit from comment:
Then the date goes into the WHERE clause, like this:
SELECT qryEmployees.EmployeeName, Count(*) AS EmpCount
FROM (Data_Servisi INNER JOIN qryEmployees ON Data_Servisi.WORKER = qryEmployees.EmployeeName) INNER JOIN City ON qryEmployees.CityID = City.CityID
WHERE Data_Servisi.V_LOCATION_VISIT_DATE BETWEEN Forms!myForm!DateStart AND Forms!myForm!DateEnd
GROUP BY qryEmployees.EmployeeName

Related

Need an aggregate MySQL select that iterates virtually across date ranges and returns bills

I have a MySQL table named rbsess with columns RBSessID (key), ClientID (int), RBUnitID (int), RentAmt (fixed-point int), RBSessStart (DateTime), and PrevID (int, references to RBSessID).
It's not transactional or linked. What it does track when a client was moved into a room and what the rent at the time of move in was. The query to find what the rent was for a particular client on a particular date is:
SET #DT='Desired date/time'
SET #ClientID=Desired client id
SELECT a.RBSessID
, a.ClientID
, a.RBUnitID
, a.RentAmt
, a.RBSessStart
, b.RBSessStart AS RBSessEnd
, a.PrevID
FROM rbsess a
LEFT
JOIN rbsess b
ON b.PrevID=a.RBSessID
WHERE a.ClientID=#ClientID
AND (a.RBSessStart<=#DT OR a.RBSessStart IS NULL)
AND (b.RBSessStart>#DT OR b.RBSessStart IS NULL);
This will output something like:
+----------+----------+----------+---------+---------------------+-----------+--------+
| RBSessID | ClientID | RBUnitID | RentAmt | RBSessStart | RBSessEnd | PrevID |
+----------+----------+----------+---------+---------------------+-----------+--------+
| 2 | 4 | 1 | 57500 | 2020-11-22 00:00:00 | NULL | 1 |
+----------+----------+----------+---------+---------------------+-----------+--------+
I also have
SELECT * FROM rbsess WHERE rbsess.ClientID=#ClientID AND rbsess.PrevID IS NULL; //for finding the first move in date
SELECT TIMESTAMPDIFF(DAY,#DT,LAST_DAY(#DT)) AS CountDays; //for finding the number of days until the end of the month
SELECT DAY(LAST_DAY(#DT)) AS MaxDays; //for finding the number of days in the month
SELECT (TIMESTAMPDIFF(DAY,#DT,LAST_DAY(#DT))+1)/DAY(LAST_DAY(#DT)) AS ProRateRatio; //for finding the ratio to calculate the pro-rated rent for the move-in month
SELECT ROUND(40000*(SELECT (TIMESTAMPDIFF(DAY,#DT,LAST_DAY(#DT))+1)/DAY(LAST_DAY(#DT)) AS ProRateRatio)) AS ProRatedRent; //for finding a pro-rated rent amount based on a rent amount.
I'm having trouble putting all of these together to form a single query that can output pro-rated and full rent amounts based on a start date and an optional end date all rent owed amounts in a single statement for each month in the period. I can add a payments table received and integrate it afterwards, just having a hard time with this seemingly simple real-world concept in a MySQL query. I'm using php with a MySQL back end. Temporary tables as intermediary queries are more than acceptable.
Even a nudge would be helpful. I'm not super-experienced with MySQL queries, just your basic CREATE, SELECT, INSERT, DROP, and UPDATE.
Examples as requested by GMB:
//Example data in rbsess table:
+----------+----------+----------+---------+---------------------+--------+
| RBSessID | ClientID | RBUnitID | RentAmt | RBSessStart | PrevID |
+----------+----------+----------+---------+---------------------+--------+
| 1 | 4 | 1 | 40000 | 2020-10-22 00:00:00 | NULL |
| 2 | 4 | 1 | 57500 | 2020-11-22 00:00:00 | 1 |
| 3 | 2 | 5 | 40000 | 2020-11-29 00:00:00 | NULL |
+----------+----------+----------+---------+---------------------+--------+
Expected results would be a list of the rent amounts owed for every month, including pro-rated amounts for partial occupancy in a month, from a date range of months. For example for the example data above for a date range spanning all of the year of 2020 from client with ClientID=4 the query would produce an amount for each month within the range similar to:
Month | Amt
2020-10-1 | 12903
2020-11-1 | 45834
2020-12-1 | 57500

Doing Math with SQL entries

so I am trying to use MySQL to look at the values of our database, and spit out the sum of the values in a column between 2 date ranges. Currently I have gotten it to at least select the correct range of dates using the code:
SELECT fuelDate, SUM(gallons)
FROM fuel566243
WHERE fuelDate BETWEEN '2019-01-04' AND '2019-01-24'
GROUP BY fuelDate
ORDER BY fuelDate
The issue with this code, is in the SUM column that gets generated, it just displays all the values of the gallons column, but doesn't add them up. Is there a way to do this in SQL and output a result? Or is it easier to just use a foreach loop to cycle through the array and add the values using PHP?
When I run the code above, it gives me this output. How do I then get the sum of the gallons column shown below? Is there a way to do that in SQL? Or would I need to use a loop to add the values using PHP?
| fuelDate | Gallons | |
| 2019-01-04 | 53.8885 | |
| 2019-01-15 | 198.1700 | |
| 2019-01-17 | 167.2750 | |
| 2019-01-23 | 176.5620 | |
| 2019-01-24 | 181.0240 | |
The GROUP BY defines the rows that are being returned. You have included gallons as an aggregation key, so you have specified that you want a separate row for each value.
Simply remove the key from the GROUP BY and the SELECT:
SELECT fuelDate, SUM(gallons)
FROM fuel566243
WHERE fuelDate BETWEEN '2019-01-04' AND '2019-01-24'
GROUP BY fuelDate
ORDER BY fuelDate;
If you want the total during the period, then you want an aggregation with no GROUP BY:
SELECT SUM(gallons)
FROM fuel566243
WHERE fuelDate BETWEEN '2019-01-04' AND '2019-01-24';

count groupings of multiple columns

I have a table of tickets to multiple dates of shows shows. basically, it looks like this...
+----+---------------+--------------+-----------+
| ID | ticket_holder | ticket_buyer | show_date |
+----+---------------+--------------+-----------+
ticket_holder and ticket_buyer are both user ids
If I wanted to count the total number of tickets that one ticket holder has, I could group by that holder and count the rows, but I want more stats than that.
I want to know a user's total bought tickets, how many they hold and how many shows they've bought tickets for.
+------+---------+--------+-------+
| USER | HOLDING | BOUGHT | DATES |
+------+---------+--------+-------+
| 1 | 12 | 24 | 7 |
+------+---------+--------+-------+
| 2 | 3 | 4 | 2 |
+------+---------+--------+-------+
| 3 | 1 | 2 | 1 |
+------+---------+--------+-------+
is it possible to put all this in a query, or do i need to do php stuff to make it happen?
I would do it in multiple queries. You can't group by either ticket_holder or ticket_buyer like you want, in a single query. If you try GROUP BY ticket_holder, ticket_buyer then it will group by both columns, which is not what you want.
SELECT ticket_holder, COUNT(*) AS tickets_held
FROM `a table of tickets` GROUP BY ticket_holder;
SELECT ticket_buyer, COUNT(*) as tickets_bought
FROM `a table of tickets` GROUP BY ticket_buyer;
SELECT ticket_buyer, COUNT(DISTINCT show_date) AS shows_bought
FROM `a table of tickets` GROUP BY ticket_buyer;
Not every task has to be accomplished in a single query! It's part of the design of SQL that it should be used by some application language, and you're expected to handle formatting and display in the application.

MySQL - Count of events across months

I have a table with events that occur & the date they occur in MySQL
The events are in column names EVENT_NAME & the occurrence is in column OCCUR_DATE. The table has hundreds of other columns. I'd like to count the occurrence of each event month by month & display the output as below.
+-------+--------+--------+--------+
| Event | Jan-15 | Feb-15 | Mar-15 |
+-------+--------+--------+--------+
| A | 0 | 1 | 0 |
| B | 6 | 6 | 3 |
+-------+--------+--------+--------+
I'm currently running SQL query manually for each month & aggregating data using Excel manually. Could I please request some assistance to write up a SQL to output the requested format?
You can try it-
SELECT event_name,
COUNT(IF(DATE_FORMAT(CURDATE(),'%b-%y')='Jan-15',1,NULL)) AS 'Jan-15',
COUNT(IF(DATE_FORMAT(CURDATE(),'%b-%y')='Feb-15',1,NULL)) AS 'Feb-15',
COUNT(IF(DATE_FORMAT(CURDATE(),'%b-%y')='Sep-15',1,NULL)) AS 'Mar-15'
FROM mytable
GROUP BY event_name;

Access 2007 Query to return latest date note from subquery

I have 2 tables joined by ProjectID in Access 2007. Table structure of primary table (A) is like
ProjectID | CustID
1 | 5
2 | 8
I have a secondary table (B) of notes on the ProjectID, structured like
ProjectNotesID | ProjectID | Note | CreateDate
---------------------------------------------------
1 | 1 | Note11 | 1/2/2015
2 | 1 | Note12 | 2/2/2015
3 | 2 | Note21 | 4/8/2015
4 | 2 | Note22 | 3/5/2015
I want to return all of, or part of, Table A, with the latest note of Table B, something like
ProjectID | CustID | Note | CreateDate
------------------------------------------
1 | 5 | Note12 | 2/2/2015
2 | 8 | Note21 | 4/8/2015
I can do (and have done) this with PHP & MySQL, but can't get it to work in Access 2007. I can return the ProjectID and latest Note date by the following query in Access 2007
SELECT ProjectID, Max(CreateDate) AS MaxOfCreateDate
FROM Table B
GROUP BY ProjectID;
I have tried Unique Values, etc., but can't get the results I am looking for.
Thanks!
Pete
I found an answer. First, I changed the query where I got the latest date, and instead got the max ProjectNotesID. The query is ::
SELECT ProjectID, Max(ProjectNotesID) AS MaxOfProjectNotesID
FROM Table B
GROUP BY ProjectID;
I then created a second query combining the above query and Table B, joining Query.MaxOfProjectNotesID <-> TableB.ProjectNotesID, and Query.ProjectID <-> TableB.ProjectID. The second query pulls all values from TableB.