Count data in every month - php

I've already research this in other question but I didn't get an answer so decide to ask here.
I have 2 tables which is the tblCourse and tblData, I have been storing all of my course list in tblCourse while in tblData I am storing the person name and what course they took. Now, what I want to do is, I want to get the total count of all the person who are taking a particular course in every month.
For example:
----------------------------------------------------------------------------
Course | Jan | feb | Mar | Apr | May | ......................| Dec | Total |
----------------------------------------------------------------------------
Course1 | 2 | 3 | 0 | 0 | 1 | ......................| 2 | 8 |
----------------------------------------------------------------------------
Course2 | 2 | 3 | 2 | 0 | 1 | ......................| 2 | 10 |
----------------------------------------------------------------------------
Course3 | 2 | 3 | 1 | 0 | 1 | ......................| 2 | 9 |
----------------------------------------------------------------------------
Here's my code:
<?php
$query = $this->db->query("SELECT * FROM tblcourse where category = 'Soft' and inex = 'inhouse' ORDER by course_name ASC");
foreach ($query->result() as $row){
?>
<tr>
<td>Id</td>
<td><?php echo $row->course_name; ?></td> // Output the Course Name
<td class="center"><?php echo $row->days; ?></td> //Output the Training days
<?php
$course = $row->course_name;
$query_jan = $this->db->query("SELECT * FROM tbldata where course like '%$course%' and course_end < '2016-11-30' and course_end >= '2016-11-01'");
?>
<td><?php echo $query_jan->num_rows(); ?></td> // Output the corresponding number of course taken by the person for the month of january
<? php
} // end of foreach
?>
Here's the structure of my database:
Table 1: tblCourse
Fields: ID, Course_name, Category, Training_days
Table 2: tblData
Fields: ID, Trainees_name, Course_taken, Date_start, Date_end
I'm just starting to develop using php.
Can I query this in a single query?

Considering Course_taken as foreign key to table tblCourse.
select tblCourse.Course_name,
Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,(Jan+Feb+Mar+Apr+May+Jun+Jul+Aug+Sep+Oct+Nov+Dec) as `Total`
from (
select
tblCourse.Course_name+
sum(CASE WHEN month(tblData.Date_start)=1 or month(tblData.Date_end)=1 THEN 1 else 0 end) as `Jan`,
sum(CASE WHEN month(tblData.Date_start)=2 or month(tblData.Date_end)=2 THEN 1 else 0 end) as `Feb`,
sum(CASE WHEN month(tblData.Date_start)=3 or month(tblData.Date_end)=3 THEN 1 else 0 end) as `Mar`,
sum(CASE WHEN month(tblData.Date_start)=4 or month(tblData.Date_end)=4 THEN 1 else 0 end) as `Apr`,
sum(CASE WHEN month(tblData.Date_start)=5 or month(tblData.Date_end)=5 THEN 1 else 0 end) as `May`,
sum(CASE WHEN month(tblData.Date_start)=6 or month(tblData.Date_end)=6 THEN 1 else 0 end) as `Jun`,
sum(CASE WHEN month(tblData.Date_start)=7 or month(tblData.Date_end)=7 THEN 1 else 0 end) as `Jul`,
sum(CASE WHEN month(tblData.Date_start)=8 or month(tblData.Date_end)=8 THEN 1 else 0 end) as `Aug`,
sum(CASE WHEN month(tblData.Date_start)=9 or month(tblData.Date_end)=9 THEN 1 else 0 end) as `Sep`,
sum(CASE WHEN month(tblData.Date_start)=10 or month(tblData.Date_end)=10 THEN 1 else 0 end) as `Oct`,
sum(CASE WHEN month(tblData.Date_start)=11 or month(tblData.Date_end)=11 THEN 1 else 0 end) as `Nov`,
sum(CASE WHEN month(tblData.Date_start)=12 or month(tblData.Date_end)=12 THEN 1 else 0 end) as `Dec`
from tblCourse
left join tblData on tblCourse.id=tblData.Course_taken
group by tblCourse.id
) data
Note : Make sure Date_start and Date_end should be of same year.

SELECT COUNT(Trainees_name) FROM tbldata where Course_taken like '%$course%' and Date_start < '2016-11-30' and Date_end >= '2016-11-01'"

Related

how to retrieve one record when multiples exist

I need help only retrieving one record per job in this dataset. There are over 900 rows in the actual result set so this is a small sample but all rows look like the below. I am already using Distinct in the query but I get more than one record for the same job,suffix,and part. I need to be able to pull only one job,suffix,part but I need each value for workcenter,hours_estimated, and hours_actual associated with each job. I'm not sure if this should/could be done in the query or by using array methods in PHP. I almost found what I am looking for here but pervasive doesn't use CTE. Can anyone assist me in trying to get my data to look like below?
Sample Data
|Job |suffix| part |PL|qty| seq |workcenter|hours_estimated|hours_actual|
----------------------------------------------------------------------------
|A02043| 001 |913036|01| 2 |000400| 0710 | 0.7491 | 2.5700 |
|A02043| 001 |913036|01| 2 |000402| 0805 | 0.6420 | 0.0000 |
|A02043| 001 |913036|01| 2 |000500| 0901 | 16.1290 | 33.1600 |
|A02043| 001 |913036|01| 2 |000600| 1520 | 0.5000 | 0.0000 |
|A02900| 001 |913104|01| 1 |000500| 0710 | 0.5280 | 1.2000 |
|A02900| 001 |913104|01| 1 |000600| 0650 | 0.8540 | 0.0000 |
What I need my PDO object/array to look like
|Job |suffix| part |PL|qty| workcenter | hours_estimated | hours_actual |
-------------------------------------------------------------------------------------------------------------------
|A02043| 001 |913036|01| 2 |0710,0805,0901,1520| 0.7491, 0.6420,16.1290,0.500| 2.57,0,33.16,0 2.5700 |
|A02900| 001 |913104|01| 1 |0710,0650 |0.5280,0.8540 |1.200,0.0000 |
Query:
select distinct v_job_header.job,v_job_header.suffix,v_job_header.part,v_job_header.product_line,v_job_header.qty_order,v_job_operations_wc.seq,v_job_operations_wc.LMO,v_job_operations_wc.workcenter,v_job_operations_wc.hours_estimated,v_job_operations_wc.hours_actual,v_job_operations_wc.flag_closed,gab_source_cause_codes.source,gab_source_cause_codes.cause
from v_job_header
left join v_job_operations_wc on v_job_operations_wc.job = v_job_header.job and v_job_header.suffix = v_job_operations_wc.suffix
left join gab_source_cause_codes on gab_source_cause_codes.job = v_job_operations_wc.job and gab_source_cause_codes.suffix = v_job_operations_wc.suffix and gab_source_cause_codes.seq = v_job_operations_wc.seq
where v_job_header.product_line = '01' and v_job_header.date_closed < '2019-01-01' and v_job_operations_wc.LMO = 'L' and v_job_operations_wc.seq < '99000'
I had to change my query
select concat(concat(v_job_header.job,'-'),v_job_header.suffix) as Job,v_job_header.part,v_job_header.qty_order,
sum(case when v_job_operations_wc.workcenter = '0750' then v_job_operations_wc.hours_actual end) as WaterJet,
sum(case when v_job_operations_wc.workcenter IN ('0705','0710','0715') then v_job_operations_wc.hours_actual end) as Laser,
sum(case when v_job_operations_wc.workcenter IN ('0600','0610','1006','0650','1315') then v_job_operations_wc.hours_actual end) as Prep,
sum(case when v_job_operations_wc.workcenter IN ('1310','0755') then v_job_operations_wc.hours_actual end) as Machining,
sum(case when v_job_operations_wc.workcenter IN ('1515','1000','1002','1003','0901','1270') then v_job_operations_wc.hours_actual end) as Fab,
sum(case when v_job_operations_wc.workcenter = '1100' then v_job_operations_wc.hours_actual end) as Paint,
sum(case when v_job_operations_wc.workcenter = '1000' then v_job_operations_wc.hours_actual end) as Belts,
sum(case when v_job_operations_wc.workcenter = '1001' then v_job_operations_wc.hours_actual end) as Electrical,
sum(case when v_job_operations_wc.workcenter = '1520' then v_job_operations_wc.hours_actual end) as Crating_Skids,
sum(case when v_job_operations_wc.workcenter IN ('1004','1005','1350','1201') then v_job_operations_wc.hours_actual end) as Final_Assy,
sum(case when v_job_operations_wc.workcenter = '4330' then v_job_operations_wc.hours_actual end) as Shipping,
sum(v_job_operations_wc.hours_estimated) as total_hours_estimated,
gab_source_cause_codes.source,gab_source_cause_codes.cause
from v_job_header
left join v_job_operations_wc on v_job_operations_wc.job = v_job_header.job and v_job_header.suffix = v_job_operations_wc.suffix
left join gab_source_cause_codes on gab_source_cause_codes.job = v_job_operations_wc.job and gab_source_cause_codes.suffix = v_job_operations_wc.suffix and gab_source_cause_codes.seq = v_job_operations_wc.seq
where v_job_header.product_line = '01' and v_job_header.date_closed < '2019-01-01' and v_job_operations_wc.LMO = 'L' and v_job_operations_wc.seq < '99000'
group by Job,v_job_header.part,v_job_header.qty_order,gab_source_cause_codes.source,gab_source_cause_codes.cause

Get Reporting data I've pivoted into a HTML table

I have a curent SQL query that reads as follows:
SELECT
WEEK,
SUM(CASE WHEN WEEK = '$week1' THEN 1 ELSE 0 END) AS week_1_total,
SUM(CASE WHEN WEEK = '$week2' THEN 1 ELSE 0 END) AS week_2_total,
SUM(CASE WHEN WEEK = '$week3' THEN 1 ELSE 0 END) AS week_3_total,
SUM(CASE WHEN WEEK = '$week4' THEN 1 ELSE 0 END) AS week_4_total,
SUM(CASE WHEN WEEK = '$week1' AND TYPE = 'refund' THEN 1 ELSE 0 END) AS week_1_refunds,
SUM(CASE WHEN WEEK = '$week2' AND TYPE = 'refund' THEN 1 ELSE 0 END) AS week_2_refunds,
SUM(CASE WHEN WEEK = '$week3' AND TYPE = 'refund' THEN 1 ELSE 0 END) AS week_3_refunds,
SUM(CASE WHEN WEEK = '$week4' AND TYPE = 'refund' THEN 1 ELSE 0 END) AS week_4_refunds,
SUM(CASE WHEN WEEK = '$week1' AND TYPE = 'closure' THEN 1 ELSE 0 END) AS week_1_closures,
SUM(CASE WHEN WEEK = '$week2' AND TYPE = 'closure' THEN 1 ELSE 0 END) AS week_2_closures,
SUM(CASE WHEN WEEK = '$week3' AND TYPE = 'closure' THEN 1 ELSE 0 END) AS week_3_closures,
SUM(CASE WHEN WEEK = '$week4' AND TYPE = 'closure' THEN 1 ELSE 0 END) AS week_4_closures,
SUM(CASE WHEN WEEK = '$week1' AND history LIKE '%rejected%' THEN 1 ELSE 0 END) AS week_1_rejections,
SUM(CASE WHEN WEEK = '$week2' AND history LIKE '%rejected%' THEN 1 ELSE 0 END) AS week_2_rejections,
SUM(CASE WHEN WEEK = '$week3' AND history LIKE '%rejected%' THEN 1 ELSE 0 END) AS week_3_rejections,
SUM(CASE WHEN WEEK = '$week4' AND history LIKE '%rejected%' THEN 1 ELSE 0 END) AS week_4_rejections
FROM
my_table
WHERE
YEAR = '$SafeFY' AND period = '$SafePeriod'
GROUP BY
WEEK
This query works and gets me the data I want, but because of how I have done it, the data has been pivoted.
I have only done it this way, because it's the only way I know how. I would like to use the result in a PHP loop like so:
echo '<table><opening tags> <etc...>'
while($Row = $Result->fetch_array(MYSQLI_ASSOC)) {
//HTML table rows with $Row['stuff'] here.
}
echo '</etc...></closing tags></table> '
But the data is the wrong way around for printing out the table like this:
| Week | Total | Refunds | Closures | Rejections |
| 1 | 44 | 32 | 12 | 3 |
| 2 | 40 | 21 | 19 | 6 |
| 3 | 40 | 22 | 18 | 3 |
| 4 | 41 | 32 | 11 | 6 |
I dont' mind either changing the query to get all the same results without the pivot so I can loop over them like I am used to doing, or doing something with the PHP array so I can loop over this queries results, whichever is easier/better. How?
Ok, I've looked at this again and I think I'm just making it harder than it needs to be.
Going on the following assumptions:
1) Databases are generally better at sorting/organising data than PHP, so changing the query is probably better than changing the array after the fact.
2)If I want the result to have 5 columns, I probably need to have five selects in the statement,
Then I looked at the GROUP BY part and realised it's already going to split the results by week anyway, so I trimmed down by sums and the GROUP BY part will then allow the results to be split into weeks already, there was no need to sum each week manually in the select part.
SELECT
WEEK,
SUM(CASE WHEN YEAR = '2019' THEN 1 ELSE 0 END) AS total,
SUM(CASE WHEN TYPE = 'refund' THEN 1 ELSE 0 END) AS refunds,
SUM(CASE WHEN TYPE = 'closure' THEN 1 ELSE 0 END) AS closures,
SUM(CASE WHEN history LIKE '%rejected%' THEN 1 ELSE 0 END) AS rejections
FROM
my_table
WHERE
YEAR = '$SafeFY' AND period = '$SafePeriod'
GROUP BY
WEEK

How to count rows in a table (phpMyAdmin)

I am currently working on an attendance system using php and mysql and I want to count the number of Present/Absent/Late of that student, which is happened on the same table. Like for example the table looks like this.
student_name | attendance status | date
| |
student1 | Present | 2019-02-21
student2 | Absent | 2019-02-21
student3 | Late | 2019-02-21
student1 | Absent | 2019-02-22
student2 | Absent | 2019-02-22
student3 | Present | 2019-02-22
I want output as below : Show how many presents/absents/late is a student in a month like
student 1 | 20 presents | 4 absents | 2 lates
I am using fpdf library but even a php code for that is a big help.
Table name : attendance_records
Solt'n
$result = mysqli_query($conn, "
SELECT student_name,
SUM(CASE WHEN attendance = 'Present' THEN 1 ELSE 0 END) AS presents,
SUM(CASE WHEN attendance = 'Absent' THEN 1 ELSE 0 END) AS absents,
SUM(CASE WHEN attendance = 'Late' THEN 1 ELSE 0 END) AS lates
FROM attendance_records
GROUP BY student_name
") or die("database error:". mysqli_error($conn));
foreach( $result as $row ) {
$pdf->SetFont('Arial','I',9);
$pdf->Ln();
foreach($row as $column) {
$pdf->Cell(39,10,$column,1);
}
}
You can combine SUM and CASE to achieve what you need
Try using query
SELECT student_name,
SUM(CASE WHEN attendance = 'Present' THEN 1 ELSE 0 END) AS presents,
SUM(CASE WHEN attendance = 'Absent' THEN 1 ELSE 0 END) AS absents,
SUM(CASE WHEN attendance = 'Late' THEN 1 ELSE 0 END) AS lates
FROM attendance_records
GROUP BY student_name
Use in phpmyadmin ..
SELECT * FROM table_name WHERE attendance_status = absent;
Phpmyadmin will count it automatically..
But you should code in php and mysql or mysqli ..

SQL Statement to Group results by two rows to create a timetable

I currently have a database table which records the bookings of jobs
and there are 8 timeslots available
+-----------+
|tbl_booking|
+-----------+
|room_id |
|date |
|timeslot |
|booking |
+-----------+
sample data
+-----------+----------+-----------+
|room_id | date | timeslot |
+-----------+----------+-----------+
|1 |2018-01-01| 1 |
|1 |2018-01-01| 2 |
|1 |2018-01-01| 4 |
|2 |2018-01-01| 1 |
+-----------+----------+-----------+
intended outcome - when statement filters for bookings on 2018-01-01
+-----------+----------+-----------+----------+-----------+
|room |timeslot1 | timeslot2 |timeslot3 | timeslot4 |
+-----------+----------+-----------+----------+-----------+
|1 | X | X | | X |
|2 | X | | | |
+-----------+----------+-----------+----------+-----------+
i started off with this statement:
SELECT * from tbl_booking WHERE date = '2018-01-01' GROUP BY room_id
and this would return results to see the results grouped by rooms.
I would like to know where i should go from here to also have the results display it's timeslots that are shown in a table displaying the booking status of eacah room's timeslot in the day?
Should there be an SQL statement that i should be using or am I on the wrong track completely?
Any help would be appreciated.
Thank you!
What you want to do with the data isn't nice to do and if you have a fixed number of time slots then you can hardcode the columns like this:
SELECT room_id,
SUM(CASE WHEN timeslot = 1 then 1 else 0 END) AS Timeslot1,
SUM(CASE WHEN timeslot = 2 then 1 else 0 END) AS Timeslot2,
SUM(CASE WHEN timeslot = 3 then 1 else 0 END) AS Timeslot3,
SUM(CASE WHEN timeslot = 4 then 1 else 0 END) AS Timeslot4
FROM tbl_booking
GROUP BY room_id
(see SQL Fiddle)
You could use MAX if you just want to see if at least 1 booking exist
SQL to include remark, you can trick it to select the remark through a group by with MAX
SELECT room_id,
SUM(CASE WHEN timeslot = 1 then 1 else 0 END) AS Timeslot1,
MAX(CASE WHEN timeslot = 1 THEN remark ELSE '' END) AS Timeslot1Remark,
SUM(CASE WHEN timeslot = 2 then 1 else 0 END) AS Timeslot2,
MAX(CASE WHEN timeslot = 2 THEN remark ELSE '' END) AS Timeslot2Remark,
SUM(CASE WHEN timeslot = 3 then 1 else 0 END) AS Timeslot3,
MAX(CASE WHEN timeslot = 3 THEN remark ELSE '' END) AS Timeslot3Remark,
SUM(CASE WHEN timeslot = 4 then 1 else 0 END) AS Timeslot4,
MAX(CASE WHEN timeslot = 4 THEN remark ELSE '' END) AS Timeslot4Remark
FROM tbl_booking
GROUP BY room_id
your extended SQL Fiddle. This won't work for multiple dates only 1 selected date
If you are looking for dynamic solutions then you must need to use pivot table.
Select * from
(select * from yourtable) as
Temptable
Pivot (
Count(room)
For timeslot
In (list of timeslot))
As tempSlot
For more information check this link MySQL pivot table

Separate Data into Days of the week mysql

Good day,
I am currently making a sales tracking report where the user pick a date range then the table should display the result.
for now I have this query that counts how many items are sold
select x_transaction_details.xitem,
SUM(x_transaction_details.qty) as totalNumberSold,
count(x_transaction_details.xitem) as occurence,
x_transaction_details.cost,
i_inventory.xitem,
x_transaction_details.date_at as transDate
from x_transaction_details
left join i_inventory on x_transaction_details.xitem = i_inventory.xid
where (x_transaction_details.date_at BETWEEN '2015-08-13 08:34:12' AND '2015-09-14 08:34:12')
GROUP BY x_transaction_details.xitem
ORDER BY occurence DESC
this query displays
|itemName| totalNumberSold | occurence | date
|item 1 | 23 pcs | 2 |
|item 2 | 18 pcs | 6 |
|item 3 | 203 pcs | 18 |
etc..
Now I want to know the breakdown of sales per day so I tried
select x_transaction_details.xitem,
SUM(x_transaction_details.qty) as sold,
count(x_transaction_details.xitem) as occurence,
x_transaction_details.cost,
i_inventory.xitem,
x_transaction_details.date_at as transDate
SUM(CASE WHEN date_at = DAYOFWEEK(1) THEN
count(x_transaction_details.xitem) END) as Sunday
from x_transaction_details
left join i_inventory on x_transaction_details.xitem = i_inventory.xid
where (x_transaction_details.date_at BETWEEN '2015-08-13 08:34:12' AND '2015-09-14 08:34:12')
GROUP BY x_transaction_details.xitem
ORDER BY occurence DESC
But its generating an error instead. I want to create a more detailed table
|itemName|Mon|Tue|Wed|Thur|Fri|Sat|Sun| totalNumberSold | occurence | date
|item 1 | 10| 0| 0 | 13 | 0 |0 |0 | 23 pcs | 2 |
|item 2 | 1 | 3| 12| 0 | 16|0 |0 | 32 pcs | 6 |
|item 3 | 0 | 6| 1 | 13 | 8 |7 |1 | 36 pcs | 12 |
etc..
Thanks for the tips, I can make this table using php (hard-way) too but I guess its doable using sql query as well. Have a good day ahead.
You are missing a comma and nesting aggregation functions. I think you want:
select i.xid, SUM(td.qty) as sold, count(td.xitem) as occurrence,
avg(td.cost) as avg_cost, i.xitem,
SUM(case when DAYOFWEEK(td.date_at) = 1 then td.qty else 0 end) as Sunday
from i_inventory i join
x_transaction_details td
on td.xitem = i.xid
where td.date_at BETWEEN '2015-08-13 08:34:12' AND '2015-09-14 08:34:12'
GROUP BY i.xid
ORDER BY occurrence DESC;
Notes:
"occurrence" has two r's.
Table aliases make the query easier to write and to read.
You can't nest aggregation functions.
You shouldn't include date_at in the select list because the value is not unique for each row.
The left join is either backwards (inventory should go first) or should be an inner join. In a properly formed database, you should not have items in the transaction table that are not in the inventory table (I don't think).
The actual code (might be helpful for anyone)
select x_transaction_details.xitem, count(x_transaction_details.xitem) as occurrence, i_inventory.xitem,
SUM(case when DAYOFWEEK(x_transaction_details.date_at) = 1 then x_transaction_details.qty else 0 end) as Sun,
SUM(case when DAYOFWEEK(x_transaction_details.date_at) = 2 then x_transaction_details.qty else 0 end) as Mom,
SUM(case when DAYOFWEEK(x_transaction_details.date_at) = 3 then x_transaction_details.qty else 0 end) as tue,
SUM(case when DAYOFWEEK(x_transaction_details.date_at) = 4 then x_transaction_details.qty else 0 end) as wed,
SUM(case when DAYOFWEEK(x_transaction_details.date_at) = 5 then x_transaction_details.qty else 0 end) as thur,
SUM(case when DAYOFWEEK(x_transaction_details.date_at) = 6 then x_transaction_details.qty else 0 end) as fri,
SUM(case when DAYOFWEEK(x_transaction_details.date_at) = 7 then x_transaction_details.qty else 0 end) as sat,
SUM(x_transaction_details.qty) as totalNumberSold
from x_transaction_details
left join i_inventory on x_transaction_details.xitem = i_inventory.xid
where (x_transaction_details.date_at BETWEEN '2015-08-13 08:34:12' AND '2015-09-14 08:34:12')
GROUP BY x_transaction_details.xitem
ORDER BY occurrence DESC
I did not used table aliases though :)

Categories