I'm creating a database to track my students' participation in classes. This is what I've set up so far. I'm working in Access 2007.
Participant Master table - name, contact info, enrolled class, enrolled semester. Enrolled class (Class A, Class B, Class C) and enrolled semester (Semester 1, Semester 2) are defined in tables. Primary key is an autoincrement number but students all get a school ID number (ParticipantID).
Query1 pulls name & address for students enrolled in class A, semester 2
(SELECT name, address FROM ParticipantMaster WHERE EnrClass = "Class A" and EnrSem = "Semester 2"). The query works.
DailySessionLog is a table to represent each daily class. Includes fields for date, instructor name (check from list), discusssion topic (check from list).
Now I want to link DailySessionLog to Query1 -- letting me check off every day whether a student was there for None, Partial, Half, or Full session that day. I'm having trouble linking these and creating a subform. Any help?
I tried having a ParticipantID field in DailySessionLog which I linked to ParticipantID in Query1. It doesn't recognize if it's a one:one or :many relationship. If I go ahead and create a subform using the Access wizard it treats the Participant data as the "higher" form and the DailySessionLog data as the "sub" form. I want it to be the other way around.
Thanks for helping!
To create a one-to-one or one-to-many relationship, you should link DailySessionLog to ParticipantMaster rather than to Query1. You would then create a query to show the daily session logs of a given class for a given semester. Example:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = "Class A" AND ParticipantMaster.EnrSem = "Semester 2"
However, it would be better to use variable parameters rather than hard-coded strings. Example:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = [ClassName] AND ParticipantMaster.EnrSem = [SemesterName]
Or, to use a value from a control on an open form:
SELECT {field list} FROM ParticipantMaster INNER JOIN DailySessionLog ON {join expression} WHERE ParticipantMaster.EnrClass = [Forms]![FormName]![ClassControlName] AND ParticipantMaster.EnrSem = [Forms]![FormName]![SemesterControlName]
EDIT
Actually, you want to use this AND xQbert's idea, so, with table names like this for brevity:
Participants (a.k.a. ParticipantMaster)
Sessions (a.k.a DailySessionLog)
ParticipantSession (a.k.a. Participant_daily_session_log)
the first query would be more like this:
SELECT {field list}
FROM
Participants
INNER JOIN ParticipantSession ON Participant.ID = ParticipantSession.ParticipantID
INNER JOIN Sessions ON ParticipantSession.SessionID = Session.ID
Where do you intend the database to "Store" the participation?
I think the problem is you need another table: a Particpiant_Daily_sessioN_log which would store the results of your daily log for each student participation.
Think about the table dailysessionlog you don't want instructor name, topic and date listed for EACH student do you?
So what you have is a many students may attend class and a class may have many students. This means you have a many to many which needs to be resolved before access can figure out what you want to do.
Think of the following tables:
Participant (ParticipantID)
Class (ClassID)
Session (SessionID, ClassID)
ClassParticipants (ClassId, ParticipantID, Semester, year
SessionParticipants (SessionID, ClassID, ParticipantID)
Related
I have an sql server database that has multiple tables that are all related to each other.
I am wondering is it possible to use FreeTextTable or ContainsTable for this?
I have only seen examples of looking at one table and search all the columns. I have not seen a case where I may have say a form. Lets call it "student application form".
On this form it may have information like
Student First Name
Student Last Name
Address
Campus they wish to study at
Tell us about yourself
Now I want to build 1 search box that will search all these tables and find this "application"
the user might type in
John Smith
Main Campus
motivated
So all tables and columns would need to be checked, but end result would be brining back the application(s) that the full text search thinks matches what was typed in.
The table structure might be like this
Application
id
firstName
lastName
campusId
AddressId
Campus
id
name
Address
id
-Name
In my real database I got like 5 or 6 tables that join with the "application" table and would all need to be accounted for.
Can this be done with full text search? Or do I have to search each table individually and somehow tie it all together again.
You can use an indexed view that concatenante all values that you want to search for...
CREATE VIEW dbo.V_FT
WITH SCHEMABINDING
AS
SELECT A.id,
CONCAT(firstName, '#', lastName, '#', C.name, '#',D.name) AS DATA
FROM dbo.Application
JOIN dbo.Campus AS C ON C.id = A.campusId
JOIN dbo.Address AS D ON C.id = A.AddressId;
GO
CREATE UNIQUE CLUSTERED INDEX X_V_APP ON dbo.V_FT (id);
GO
Then create an FT index on DATA colums of the indexed view
My requirement is like below.
InstituteId is passed as parameter to my query, i need to get all the studentId's who are enrolled in any of the courses the institute is offering and they should be full time students..
There are chances that few users have registered but they are not enrolled in any courses, few users have enrolled on more than 1 course and in this case i need to display this user only once.
SELECT DISTINCT s.StudentId, f.[RegistrationId] from dbo.[Student] s
INNER JOIN dbo.FulltimeStudent f on s.StudentId = f.StundentId
WHERE CourseId in (
SELECT CourseId from dbo.[Institute] WHERE InstituteId = #InstututeId
)
I am seeing some performance lag with the above, I am seeing if there is any better approach to accomplish the above ?
I wonder how the instructor is represented in the vast Moodle DB. Where is the specific table with attribute columns to store data for every teacher?
Although there is something relevant like the diagram above, i need something to describe the teacher table.
Any ideas?
picture taken from : http://www.examulator.com/er/
Moodle has the following default archetypes for what you refer to as an instructor;
manager
coursecreator
editingteacher
teacher
A user can be assigned one of these roles in a particular context, a context such as a course or perhaps course category.
The database stores the teacher data across a number of tables. Looking at the database schema diagram you have shown, the tables you are looking for are in the roles grouping. Specifically role and role_assignments. By linking these tables with the user, context and course tables, you can find the staff associated with courses.
An example function to get the staff associated with a particular course would be
function get_course_staff($courseid) {
global $DB;
$sql = "SELECT u.firstname,
u.lastname
FROM {role_assignments} ra
WHERE c.contextlevel = 50 // Numeric value of the course context
AND c.instanceid = ?
AND r.id < 5
JOIN {role} r ON ra.roleid = r.id
JOIN {user} u ON ra.userid = u.id
JOIN {context} c ON ra.contextid = c.id
JOIN {course} co ON c.instanceid = co.id
ORDER BY r.sortorder ASC";
return $DB->get_records_sql($sql, array($courseid));
}
A role can be assigned to many users.
A user can have many roles.
A user is assigned a role in a particular context.
I have 3 tables:
Persons(PersonID, PersonName, PersonAge, PersonType)
Students(StudentID (fk to Persons.PersonID), StudentRank, StudentClassID, ...)
Teachers(TeacherID (fk to Persons.PersonID), TeacherSalary, ...)
A person can be only one type: student or teacher. So if I want to list all person with the type (student or teacher), I need to check PersonType of Persons table, then join with corresponding table (Students, Teachers)? Is it good enough? Anyone can give me a better solution?
Edit: I use combo: PHP + MySQL.
Update: Structure of tables.
The...
SELECT * FROM Persons JOIN Students ON Persons.PersonID = Students.StudentID
...will not return any teachers.
So you don't have to filter on PersonType (but may want to in more complex cases, if it's indexed in a way that aids performance).
--- EDIT ---
OK, so you want to "cram" everything together then sort on PersonName. You can do that by carefully filling the "gaps" between two child tables with NULLs:
SELECT *
FROM (
SELECT Persons.*, StudentRank, StudentClassID, NULL TeacherSalary
FROM Persons JOIN Students ON Persons.PersonID = Students.StudentID
UNION ALL
SELECT Persons.*, NULL StudentRank, NULL StudentClassID, TeacherSalary
FROM Persons JOIN Teachers ON Persons.PersonID = Teachers.TeacherID
) Q
ORDER BY PersonName
There are two techniques that will help you, they are explained in the info tab under
class-table-inheritance
shared-primary-key
Your current design reflects much of class table inheritance. What shared primary key will buy you
is the ability to enforce the one to one nature of the relationship between students and persons, and between teachers and persons. It will not enforce a mutually exclusive relationship between teachers and students.
With two joins and a union, you can combine these three tables into a view that captures all this data, with NULLs in places that are not applicable.
You can use find_in_set than u need not to join the two tables:
select p.Personname
from students s,persons p
where find_in_set(s.Studentid,p.Personid)
Relatively new to JPA, so I have one kind of architectural question.
Let's say I have tables EMPLOYEE and DEPARTMENT with many to one relationship (i.e. many employees work for one department):
EMPLOYEE
EMPLOYEE_ID
EMPLOYEE_NAME
DEPARTMENT_ID
DEPARTMENT
DEPARTMENT_ID
DEPARTMENT_NAME
So I can define proper entities for Employee and Department, there's no problem. However, in one view I would like to display list of departments with number of employees working for that department, something like this:
SELECT D.DEPARTMENT_NAME,
(SELECT COUNT(*) FROM EMPLOYEE E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID) NUMBER_OF_EMPLOYEES
FROM DEPARTMENT D
I'm just not sure what is the right strategy to accomplish this using JPA...
I don't want to always fetch number of employees for Department entity, as there is only one view when it is needed.
It looks like Hibernate's #Formula would be one possible approach, but afaik it does not conform with JPA standard.
You can create any object in your QL using the "new" syntax - your class just needs a constructor that takes the values returned by your query.
For example, with a class like DepartmentEmployeeCount, with a constructor:
public DepartmentEmployeeCount(String departmentName, Integer employeeCount)
you could use QL something like:
SELECT NEW DepartmentEmployeeCount(D.DEPARTMENT_NAME, count(E.id)) from Department D left join D.employees E GROUP BY D.DEPARTMENT_NAME
Or if you were just selecting the count(*) you could simply cast the query result to a Number.
Alternatively, to do the same without the DepartmentEmployeeCount class, you could leave out the NEW, so:
SELECT D.DEPARTMENT_NAME, count(E.id)
This would return a List<Object[]> where each list item was an array of 2 elements, departmentName and count.
To answer your later question in the comments, to populate all fields of a Department plus a transient employeeCount field, one suggestion would be to do 2 queries. This would still be more efficient than your original query (a subselect for each employee count).
So one query to read the departments
SELECT D from Department D
giving you a List<Department>
Then a 2nd query returning a temporary array:
SELECT D.DEPARTMENT_ID, count(E.id) from Department D left join D.employees E GROUP BY D.DEPARTMENT_ID
giving you a List<Object[]> with DEPARTMENT_ID and count in it.
Then you use the 2nd list to update the transient count property on your first list.
(You could try selecting into a Map to make this lookup easier, but I think that's a Hibernate feature).
Option 1: I suggested this since you didn't like the constructor route MattR was suggesting. You mentioned the word "view" several times, and I know you were talking about the view to the user, but why not setup a view in your database that includes the computed columns and then create a read-only entity that maps to the computed columns?
Option 2: In response to your comment about not wanting to create a view. You could create a container object that holds the entity and the calculated column, then much like MattR suggests, you use a new in your select. Something like:
public class DepartmentInfo {
private Department department;
// this might have to be long or something
// just see what construct JPA tries to call
private int employeeCount;
public DepartmentInfo( Department d, int count ) {
department = d;
employeeCount = count;
}
// getters and setters here
}
Then your select becomes
SELECT new my.package.DepartmentInfo( D,
(SELECT COUNT(*) FROM EMPLOYEE E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID))
FROM DEPARTMENT D
With that you can use the DepartmentInfo to get the properties you are interested in.
You could create a member in your entity as an additional column, and then reference it with an alias in your query. The column name in the #Column annotation must match the alias.
Say, for your original query, you can add a countEmployees member as following. Also add insertable=false and updatable=false so the entity manager wont try to include it in insert or update statements:
public class Department {
#Column(name="DEPARTMENT_ID")
Long departmentId;
#Column(name="DEPARTMENT_NAME")
String departmentName;
#Column(name="countEmployees", insertable=false, updatable=false)
Long countEmployees;
//accessors omitted
}
And your query:
SELECT D.DEPARTMENT_NAME,
(SELECT COUNT(*) FROM EMPLOYEE E WHERE E.DEPARTMENT_ID = D.DEPARTMENT_ID) AS countEmployees
FROM DEPARTMENT D
This also applies when working with Spring Data Jpa Repositories.