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;
Related
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
I have this table (Pickups):
+-----------+------------+-------------+------------+
| worker_id | box_weight | bag_weight | date |
+-----------+------------+-------------+------------+
| 1 | 2 | 5 | 11-07-2018 |
| 1 | 7 | 9 | 11-07-2018 |
| 2 | 8 | 11 | 11-07-2018 |
| 2 | 7 | 12 | 11-07-2018 |
+-----------+------------+-------------+------------+
and I want in Laravel 5.4 Eloquent database engine get the sum of the box_weight and the bag_weight like this:
+-----------+-----------------+-----------------+------------+
| worker_id | sum(box_weight) | sum(bag_weight) | date |
+-----------+-----------------+-----------------+------------+
| 1 | 9 | 14 | 11-07-2018 |
| 2 | 15 | 23 | 11-07-2018 |
+-----------+-----------------+-----------------+------------+
Until now I could only retrieve the sum of a single column not the both in the same call.
Please find the answer bellow, since you didn't mention you want sum of same date per worker id or all dates, I assume only same date, if you want sum of all dates per worker id, remove date from groupBy
Eloquent Query
Pickup::select(['worker_id ','date',DB::raw('sum(box_weight)'),DB::raw('sum(bag_weight)')])
->groupBy('worker_id','date')
->get();
or in Query Builder Approach
DB::table('pickups')
->select(['worker_id ','date',DB::raw('sum(box_weight)'),DB::raw('sum(bag_weight)')])
->groupBy('worker_id','date')
->get();
You're looking for the MySql query or Laravel's QueryBuilder/Eloquent?
I'm assuming you want it grouped by worker_id and not by date, if it's by date, just add date to the groupBy
In the future, show us what you've tried and you're trying to accomplish in more detail
If you're looking for the MySqlQuery, Rom's answer will do just fine
SELECT worker_id, sum(box_weight), sum(bag_weight), date
FROM pickups
GROUP BY worker_id
If you're going from the Eloquent model:
//Assuming Pickup is your model name
Pickup::selectRaw('worker_id, sum(box_weight), sum(bag_weight), date')
->groupBy('worker_id')->get();
Using DB
DB::table('pickups')->selectRaw('worker_id, sum(box_weight), sum(bag_weight), date')
->groupBy('worker_id')->get();
//Or even
DB::select(DB::raw('SELECT worker_id, sum(box_weight), sum(bag_weight), date
FROM pickups
GROUP BY worker_id');
This will give you a collection of pickups, place toArray() at the end of the query if you wish to convert it to an array
The reason behind selectRaw is due to not being able to use ->sum() with ->select(). It works just fine for the sum of a column, not for multiple output and the same goes for select, as it can't relate sum(column) as a column
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
I have a database which looks like this:
Reservations Table:
-------------------------------------------------
id | room_id | start | end |
1 | 1 | 2015-05-13 | 2015-05-16 |
2 | 1 | 2015-05-18 | 2015-05-20 |
3 | 1 | 2015-05-21 | 2015-05-24 |
-------------------------------------------------
Apartment Table:
---------------------------------------
id | room_id | name |
1 | 1 | test apartment |
---------------------------------------
Meaning that in the month 05 (May) there is 31 days in the database we have 3 events giving us 8 days of usage 31 - 8 = 23 / 31 = 0.741 * 100 = %74.1 is the percentage of the emptiness and %25.9 is the percentage of usage. how can i do all of that in SQL? (mySQL).
This is my proposal:
SELECT SUM(DAY(`end`)-DAY(`start`))/EXTRACT(DAY FROM LAST_DAY(`start`)) FROM `apt`;
LAST_DAY function gives as output the date of last day of the month.
Check this
http://sqlfiddle.com/#!9/7c53b/2/0
Not the most efficient query but will get the job done.
select
sum(a.days)*100/(SELECT DAY(LAST_DAY(min(start))) from test1)
as usePercent,
100-(sum(a.days)*100/(SELECT DAY(LAST_DAY(min(start))) from test1))
as emptyPercent
FROM
(select DATEDIFF(end,start) as days from test1) a
What I did is first get the date difference and count them. Then in a nested query use the day(last_day()) function to get the last day of month. Then calculated by using your logic.
I have a view set up like the below table, which is pulling data from multiple other tables using JOINS. Basically I'm trying to replicate a Crystal Report that breaks up the data below into Job # - Weekly (hrs) - TotalToDate(hrs) - Budget(hrs)
And this is broken up per department. The way the report does it is it'll display the hours for the last week, then the total hours to date then the budgeted hours set for that department.
Table doesn't reflect above - just an example of what DB table looks like.
+-----------+------------+---------------+--------+---------------------+
| Job | Work_Date | Work_Center | Est_Total_Hrs | Act_Run_Hrs |
+-----------+------------+---------------+--------+------+--------------+
| 5666 | 2014-02-23 | SURFACE | 155 | 5 |
| 5666 | 2014-02-16 | SURFACE | 155 | 3 |
| 5666 | 2014-02-23 | DESIGN | 200 | 6 |
| 5666 | 2014-02-16 | DESIGN | 200 | 4 |
| 5666 | 2014-02-23 | SURFACE | 150 | 2 |
| 5666 | 2014-02-16 | SURFACE | 150 | 2 |
| 5666 | 2014-02-23 | DESIGN | 300 | 8 |
+-----------+------------+---------------+---------------+--------------+
Also, theres a lot of different job numbers, and when I pull up more than 1 job in Crystal it'll show the report like the picture above but with all jobs I want to retrieve.
How would I go about pulling this data so it shows up the same way in the Crystal Report? I want to create a view that looks the same. Is there a way to see how Crystal does it? When I click "Show Query" it shows me the below query which I had to re-write a little bit for it to work in SQL Server and in Adminer.
Query I'm using to pull ALL data for all Jobs within an updated Work_Date in the last 90 days.
SELECT Job_Operation.Work_Center
,Job_Operation.Job_Operation
,Job_Operation_Time.Work_Date
,Job_Operation.Est_Total_Hrs
,Job_Operation_Time.Act_Run_Hrs
,Job_Operation_Time.Act_Setup_Hrs
,Job.Description
,Job_Operation_Time.Overtime_Hrs
,Job_Operation_Time.Act_Setup_Hrs
,Job.Job
,Job.Description
,Job_Operation_Time.Labor_Burden
,Job_Operation.Est_Setup_Labor
,Job_Operation.Est_Run_Labor
,Job_Operation.Est_Labor_Burden
,Job_Operation.Operation_Service
FROM Job AS Job
LEFT OUTER JOIN Job_Operation AS Job_Operation ON Job.Job = Job_Operation.Job
LEFT OUTER JOIN Job_Operation_Time AS Job_Operation_Time ON Job_Operation.Job_Operation = Job_Operation_Time.Job_Operation
WHERE DATEDIFF(day, Work_Date, GETDATE()) < 90 ORDER BY Work_Date Desc
Crystal will take the data from a query and does its internal manipulation as per the design of the report, So if you need the table exactly as you view the report then along with the query in crystal report you need to make some changes.
Suggestions:
Your report has only 6 columns but you query has more than 10 columns so you need to change the query so that it has only 6 columns.
Report has data according to the week but query has hourly data so you need to write some functions in query so that you manage to get weekly data from hour data
You said when you take more than 1 ID you get in the given format then in that case add some group by conditions to the resultant query so that all data is grouped. for e.g if you need only one ID then group by ID so that there is only one record for a ID.
Try adding some group by conditions some date formulas to get exact output