Correct mySQL query for Student attendance entry - mysql

I'm trying to develop a student attendance form using Codeigniter & MySQL. My table structure for the two tables are as follows:
student_mst table
-----------------
s_id(pk)
s_name
s_acssn_id
s_prog_id
s_admission_no
s_photo_name
stu_attendance table
--------------------
sa_id(pk)
sa_s_id(fk)
sa_s_acssn_id
sa_s_prog_id
sa_atten_dt
sa_atten_code(A=Absent,P=Present)
sa_teacher_id
The design of my interface is as shown in the image below:
My plan is, on any particular date, a teacher can mark a student as either Present or Absent from the Action buttons for which ajax code is there which inserts rows in the above-mentioned stu_attendance table. And also every new day when the attendance entry form is opened, the Datatable plugin should open just like as shown in the image.
In order to accomplish my plans, I'm populating a Datatable plugin using the following query:
SELECT a.s_id AS sid,a.s_prog_id AS progid,a.s_acssn_id AS ssnid,a.s_name AS sname,a.s_admission_no AS sadmsnno,a.s_photo_name AS sphotonm,
b.sa_atten_code AS acode
FROM student_mst a
LEFT JOIN stu_attendance b
ON a.s_id = b.sa_s_id
The above SQL query works well for the first time (i.e. when stu_attendance table is empty)
and populates the Datatable plugin as shown in the above image. I'm able to mark students as Present/Absent.
However, my plan fails the next day, because as per the query written above, it also picks and shows records of the students from the previous day which is not desired.
I hope I have made my problems clear. Anyone, please guide me. Should I change my table structures or should I change my design interface or should change my SQL query. Please help maybe with some code/examples.

Add a date check to the join so it only shows the current day's attendance.
SELECT a.s_id AS sid,a.s_prog_id AS progid,a.s_acssn_id AS ssnid,a.s_name AS sname,a.s_admission_no AS sadmsnno,a.s_photo_name AS sphotonm,
b.sa_atten_code AS acode
FROM student_mst a
LEFT JOIN stu_attendance b
ON a.s_id = b.sa_s_id AND b.sa_atten_dt = CURRENT_DATE()

use a where condition at the end of your query.
for example:
where date like '%19%August%';

Use following query, it should work
SELECT a.s_id AS sid,a.s_prog_id AS progid,a.s_acssn_id AS ssnid,a.s_name AS
sname,a.s_admission_no AS sadmsnno,a.s_photo_name AS sphotonm,
b.sa_atten_code AS acode
FROM student_mst a
LEFT JOIN stu_attendance b
ON a.s_id = b.sa_s_id AND b.sa_atten_dt >= date_format(curdate(),'%Y-%m-%d %H:00:00')

Related

Getting a list from the first record from inner join

Let's say I have a table named costumer. Those customers have evolutions where I take notes from contacts that are made.
So the costumer table will have the basic information and the the evolutions will have what it needs and a field to point out the customer. Let's say costumer_id.
This will be a One to Many relation and I need to export several CSVs from mysql with a list of the clients when the first evolution was created (evolution.created_at) for a given month.
Been going around and I can't make the query work. Can someone help me? Thanks in advance
You could simply do a select that looks something like this:
SELECT
c.customer_id
min(e.created_at)
FROM
costumer c
inner join evolution e on
e.costumer_id = c.costumer_id
-- Not sure what you mean by given month
where e.month = 'April'
group by c.customer_id

JOIN data from bridging table

I'm taking a database class and I'm having troubles with using the JOIN command to get the data I need. I hope I'm on the right track...I would appreciate any inputs if there is a better way both in my model and query.
Sales transaction that each employee has processed
, I'm trying to answer the following question:
Here is a query I tried but fail to come up with correct output. I had to use a table alias for sales because I kept getting unique errors. I only have 10 rows in my bridging table however, I got 100 results back...JOIN statements are kicking my butt right now.
SELECT sales.cashier, inventory.prod_name, inventory.unit_price
FROM inventory, sales
JOIN inv_sales ON inventory_prod_id = inventory.prod_id
JOIN sales AS sales1 ON sales_sales_id = sales_id;
edit: Additional requested data
Here is a screenshot of some sample data.
I had to put them all on one pic due to site restrictions.
Tables:
Top, Inv_sales
Middle, Sales
Bottom, Inventory
Expected output:
cashier > product name > unit price
You might try something like this:
SELECT s.cashier, i2.prod_name, i2.unit_price
FROM sales s
JOIN inv_sales i1
ON i1.sales_sales_id = s.sales_id
JOIN inventory i2
ON i1.inventory_prod_id = i2.prod_id
ORDER BY s.cashier,s.date;
It uses a unique alias for each table, and uses the modern form of joining tables. Also, since the requirement was to get the sales for each employee, I added an order by so an employees sales would be grouped together.

What's wrong with this mySQL logic?

In table "Booking" I hold details of a customer's booking (date/time/RowNumber).
In table "Seat" I hold details of all seats (RowNumber and Zone) in the theater.
The purpose of this query is to join Seat to Booking to see which seats are taken by displaying those rows in Seat which have a null entry in the corresponding Booking RowNumber. Here is the code:
SELECT s.Zone, s.RowNumber
FROM Booking b JOIN Seat s
ON s.RowNumber = b.RowNumber
WHERE b.PerfDate = '2016-12-12'
AND b.PerfTime = '20:30:00'
AND b.RowNumber is null;
The code is accepted but the result comes back as an empty set with the last AND statement or just shows what is in bookings without it. There is clearly something wrong with the logic I am using but I cannot pinpoint it as what I am trying to do makes sense when I read it. Probably an obvious mistake but some help would be appreciated.
Thank you in advance.
[Edit - I have spotted the logic error... it is the fact that I am asking for specific date and time when the records I want don't have those by definition but no idea how to get round it, seems like catch 22.]
You need to use a LEFT JOIN, and put all the criteria for the non-matching row into the ON clause.
SELECT s.zone, s.RowNumber
FROM Seat AS s
LEFT JOIN Booking AS b
ON s.RowNumber = b.RowNumber AND b.PerfDate = '2016-12-12' AND b.PerfTime = '20:30:00'
WHERE b.RowNumber IS NULL

MySQL Inner Join Against an Inner Join?

I have 3 tables "Employees", "EmployeeLeaveDays" and "EmployeeLeaves".
I'm looking to create a view that displays the date of the leave and the employee name. So in order for my calendar to work I have split everyones leave into individual days(EmployeeLeaveDays) which has an FK that links each day back to (EmployeeLeaves) which has other details around the leave, in EmployeeLeaves I have a column "employee" which is an FK back to employees which contains the name.
So In my view I want to return the name as you can see is 2 tables away, I've wrote this MySQL query but it doesn't work (returns no data), I'm wondering if there is anyway to do what I need to do?
SELECT
EmployeeLeaveDays.id,
EmployeeLeaveDays.employee_leave,
EmployeeLeaveDays.leave_date,
EmployeeLeaveDays.leave_type
FROM EmployeeLeaveDays
INNER JOIN EmployeeLeaves
ON EmployeeLeaveDays.employee_leave=EmployeeLeaves.employee
INNER JOIN Employees
ON EmployeeLeaves.employee=Employees.employee_id;
Hopefully from that you're able to see what I'm trying to achieve, how ever I've attached some screenshots of the table structure.
Thanks
After some thinking I got there in the end. Here's the final query.
SELECT
EmployeeLeaveDays.id,
EmployeeLeaveDays.employee_leave,
EmployeeLeaveDays.leave_date,
EmployeeLeaveDays.leave_type,
EmployeeLeaves.employee,
Employees.employee_id,
Employees.first_name,
Employees.last_name
FROM EmployeeLeaveDays
LEFT JOIN EmployeeLeaves ON EmployeeLeaveDays.employee_leave = EmployeeLeaves.id
LEFT JOIN Employees ON EmployeeLeaves.employee = Employees.id;

Remove duplicates from LEFT JOIN query

I am using the following JOIN statement:
SELECT *
FROM students2014
JOIN notes2014 ON (students2014.Student = notes2014.NoteStudent)
WHERE students2014.Consultant='$Consultant'
ORDER BY students2014.LastName
to retrieve a list of students (students2014) and corresponding notes for each student stored in (notes2014).
Each student has multiple notes within the notes2014 table and each note has an ID that corresponds with each student's unique ID. The above statement is returning a the list of students but duplicating every student that has more than one note. I only want to display the latest note for each student (which is determined by the highest note ID).
Is this possible?
You need another join based on the MAX noteId you got from your select.
Something like this should do it (not tested; next time I'd recommed you to paste a link to http://sqlfiddle.com/ with your table structure and some sample data.
SELECT *
FROM students s
LEFT JOIN (
SELECT MAX(NoteId) max_id, NoteStudent
FROM notes
GROUP BY NoteStudent
) aux ON aux.NoteStudent = s.Student
LEFT JOIN notes n2 ON aux.max_id = n2.NoteId
If I may say so, the fact that a table is called students2014 is a big code smell. You'd be much better off with a students table and a year field, for many reasons (just a couple: you won't need to change your DB structure every year, querying across years is much, much easier, etc, etc). Perhaps you "inherited" this, but I thought I'd mention it.
GROUP the query by studentId and select the MAX of the noteId
Try :
SELECT
students2014.Student,
IFNULL(MAX(NoteId),0)
FROM students2014
LEFT JOIN notes2014 ON (students2014.Student = notes2014.NoteStudent)
WHERE students2014.Consultant='$Consultant'
GROUP BY students2014.Student
ORDER BY students2014.LastName