Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to figure out a good way to build a database for events. I have a client that has a list of customer names and promo codes. A customer on the list can go to a landing page, fill out the promo code and choose an event from a drop down field they would like to attend. He currently has 4 events ready to go.
In the database, should I create 4 tables, one for each event with customers or separate the customers from the event tables (ie...customer table and 4 event tables). There might be more events in the future so scalable options would be preferred.
Also, each customer is only aloud a maximum number of 4 tickets and they can only use the promo code once.
Thanks!
Jay is correct that a complete answer would be quite long, but I'll offer a few starting pointers nonetheless as it sounds like you're quite new to database architecture.
As a general principle, you should never build a schema that involves adding/removing tables at run time. The relationship you're looking for between customers and events is many-to-many, which in MySQL would use a junction table. An example schema would look like this:
customer
customer_id (primary key)
email, name, etc.
event
event_id (primary key)
name, time, etc.
ticket
ticket_id (primary key)
customer_id (index)
event_id (index)
date_purchased, etc.
Rules like "each customer is only allowed 4 tickets" should be implemented at a code level rather than a schema level since that is subject to change and your schema should be flexible enough to accommodate that change, tempting as it may be to have four columns in the customers table for the four tickets.
To get the events that customer ID 1 is attending:
SELECT DISTINCT event.*
FROM ticket
LEFT JOIN event ON ticket.event_id = event.event_id
WHERE ticket.customer_id = 1
To get the customers attending event ID 1:
SELECT DISTINCT customer.*
FROM ticket
LEFT JOIN customer ON ticket.customer_id = customer.customer_id
WHERE ticket.event_id = 1
A common format for junction tables is to combine the two table names, as in event_customer, but in this case calling it ticket makes more sense, since you might be including additional information about the ticket purchase in that table.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a website for a project that needs to summarize all of the budget categories in one column.
For example I have a column which contains:
Categories:
Water,Electricity,Gas,Rentals,Hospital Fees,Medicine,Personal Care,Fitness,
I want to select the sum of
water,electricity,gas,rentals
and name it as utility bills.
Same as sum of
hospital fees, medicine, personal care, fitness
as healthcare.
What sql statement should i use?
Any help will be appreciated
You'd have some other table perhaps, or another column on this table, that maps the specific bills to a general group or category
You would then run a query like (if you put the category group in the main table)
SELECT categorygroup, sum(amount)
FROM bills
GROUP BY categorygroup
Or (if you have a separate table you join in)
SELECT bcg.categorygroup, sum(amount)
FROM bills b INNER JOIN billcategorygroups bcg ON b.category=bcg.category
GROUP BY bcg.categorygroup
You would then maintain the tables, either like (category in main table style):
Bills
Category, CategoryGroup, Amount
---
Electricity, Utility, 123
Water, Utility, 456
Or (separate table to map categories with groups style)
BillCategoryGroups
Category, CategoryGroup
---
Water, Utility
Electricity, Utility
Etc
Something has to map electricity -> utility, water -> utility etc. I'd probably have a separate table because it is easy to reorganize. If you decide that Cellular is no longer Utility but instead Personal then just changing it in the mapping table will change all the reporting. It also helps prevent typos and data entry errors affecting reports - if you use the single table route and put even one Electricity bill down as Utitily then it gets its own line on the report. Adding new categories is easy with a separate table too. All these things can be done with single table and big update statements etc but we have "normalization" of data for good reasons
You may use conditional aggregation. Like
SELECT project,
SUM(CASE WHEN category IN ('water','electricity','gas','rentals')
THEN spent
ELSE 0
END) AS bills,
SUM(CASE WHEN category IN ('hospital fees','medicine','personal care','fitness')
THEN spent
ELSE 0
END) AS healthcare
FROM datatable
GROUP BY project;
But the data normalization is the best option. All categories must be moved to separate table. See Caius Jard's answer.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
i want an answer to this question as i have search the internet and not found. the question is
"How should data be structured to facilitate JOIN clauses in a one-to-many relationship? What about a many-to-many relationship?"
In case of one-to-many you should insert the id of the referenced item in the table that is on the many side.
one-to-many case
A person can own many cars but a car is owned by only one person.
In a relational database this is translated with the creation of the person_id inside the car entity. In this way you can retrieve all the cars owned by a person with a simple join.
In case of a many-to-many relationship, you need to create a bridge table between the two entities.
Get owners of the Mazdas query Example
SELECT name, surname
FROM car JOIN person ON car.person_id = person.id
WHERE car.brand = 'mazda'
many-to-many case
Example:
Let's suppose that the requirement has been changed and a car can be owned by many people.
This is translated by adding a new bridge table (e.g. person_car) that has the following columns:
person_car_id
car_id
person_id
other_columns_that_could_map_the_relationship (e.g. is_the_main_owner)
Get owners of the Mazdas query Example
SELECT DISTINCT name, surname
FROM car JOIN person_car ON person_car.id_car = car.id JOIN person ON person_car.person_id = person.id
WHERE car.brand = 'mazda'
If you see here you can map many-to-many relationship between the two entities and perform a double JOIN (passing through the bridge table) to retrieve the elements.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm working on a database for work, and I need to figure out a way for Access to count the number of projects that each employee is assigned. Projects have 1 or 2 employees assigned, and my boss needs to be able to quickly figure out how many projects each person is working on. Below is an example table:
Project Employee 1 Employee 2
Project A John Doe Jane Doe
Project B Jane Doe Sam Smith
Project C Jane Doe John Doe
Project D Sam Smith Anna Smith
Project E Anna Smith John Doe
And here is the result I'm looking for:
**Employee # of Projects**
John Doe 3
Jane Doe 3
Sam Smith 2
Anna Smith 2
The table you described is probably not the best way to store the data and I think it's only making your job more difficult. The value of a relational database is that you can have data living in different tables but related based on primary/ foreign keys which makes it significantly easier to pull reports like the one you described. It seems to me like this table might have previously lived in Excel, and I would spend some time now establishing relationships in Access which will save you time and headaches later. I would suggest creating 3 separate tables: employees, projects, and project employee assignments.
The employee table should have 3 fields: EmployeeID, which should be set to AutoNumber in Design view and then selected as the primary key, First Name, and Last Name, both short text fields. This EmployeeID field will be referenced in the project employee assignments table.
The projects table should have 2 fields: ProjectID, also set to AutoNumber in Design view and selected as the primary key, and ProjectName which will also be a short text field. You can also add other fields, perhaps a text field for ProjectDescription would be helpful later on.
The Project-Employee Assignments table should have 2 fields: EmployeeID and ProjectID. If you aren't familiar with one-to-one, one-to-many, and many-to-many relationships I would suggest looking it up- you are describing a many-to-many relationship between the projects and employees, that is, one project can have many employees and one employee can be involved in many projects. This table exists to establish those relationships between employees and projects.
From here, go to the database tools tab and select Relationships. You'll need to establish a one-to-many relationship between the Employees table and the Assignments table on the EmployeeID field. You'll also need to establish a one-to-many relationship between the Projects table and the Project-Employee Assignments table on the ProjectID field.
Enter each relationship between projects and employees in the Assignments table. If you have a short list of projects and employees, you can do this directly in the table, but I'd suggest creating a form to do this with 2 combo boxes that each select from the lists of existing projects and employees, respectively. There are many tutorials about creating combo boxes that show informative columns, like employee name, but save the ID numbers to the table. Search "Bind Combo Box to Primary Key but display a Description field" for one example.
Finally, create a query to count projects per employee. You should include your Employees table, as well as your Project-Employee Assignments table. Select FirstName and LastName from the Employees table. Select both columns (EmployeeID and ProjectID) from the Project-Employee Assignments table. Unclick "show" for EmployeeID. Right-click anywhere in the query to get a menu of more options and click the sigma for totals. Set the total for EmployeeID, FirstName, and LastName to "Group By" and for ProjectID to "Count" then save the query. Run the query and enjoy having your totals!
Elizabeth Ham's answer is very thorough and I recommend following her advice, but knowing that sometimes we don't have time to do a complete overhaul, here's some instructions on how to get results from the given table structure. As Elizabeth and I pointed out (in my comment), a single query could have gotten the requested data if the tables were complete and properly normalized.
Because there are multiple employee columns for which you want statistics, you need to join the given table at least twice, each time grouping on a different column and using a different alias. It is possible to do this using the visual Design View, however it is usually easier to post questions and answers on StackOverflow using SQL text, so that's what follows. Just paste the following code into the SQL view of a query, then you should be able to switch between SQL view and Design View.
Save the following SQL statements as two separate, named queries: [ProjectCount1] and [ProjectCount2]. Saving them allows you to refer to these queries multiple times in other queries (without embedding redundant subqueries):
SELECT P.[Employee 1] As Employee, Count(P.Project]) As ProjectCount
FROM Project As P
GROUP BY P.[Employee 1];
SELECT P.[Employee 2] As Employee, Count(P.[Project]) As ProjectCount
FROM Project As P
GROUP BY P.[Employee 2];
Now create a UNION query for the purpose of creating a unique list of employees from the two source columns. The UNION will automatically keep only distinct values (i.e. remove duplicates). (By the way, UNION ALL would return all rows from both tables including duplicates.) Save this query as [Employees]:
SELECT Employee FROM [ProjectCount1]
UNION
SELECT Employee FROM [ProjectCount2]
Finally, combine them all into a list of unique employees with a total sum of projects for each:
SELECT
E.Employee As Employee, nz(PC1.ProjectCount, 0) + nz(PC2.ProjectCount, 0) As ProjectCount
FROM
([Employees] AS E LEFT JOIN [ProjectCount1] As PC1
ON E.[Employee] = PC1.[Employee])
LEFT JOIN [ProjectCount2] As PC2
ON E.[Employee] = PC2.Employee
ORDER BY E.[Employee]
Note 1: The function nz() converts null values to the given non-null value, in this case 0 (zero). This ensures that you'll get a valid sum even when an employee appears in only one column (and as such has a null value in the other column).
Note 2: This solution will double count an employee if it's listed as both [Employee 1] and [Employee 2] in the original table. I assume that there are proper constraints to exclude that case, but if needed, one could do a self join on the second query [ProjectCount2] to exclude such double entries.
Note 3: If you do decide to follow Elizabeth's advice and you already have a lot of data in the existing structure, the above queries can also be useful in generating data for the new, normalized table structure. For instance, you could insert the unique list of employees from the above UNION query directly into a newly normalized [Employee] table.
I have a question regarding extending a table in mysql.
Let's assume that we have a user table
User:
user_id
user_name
Let's assume that this is user is used in a company which has multiple departments.
Now if the HR department want the user to have birthday and hire date fields only, but finance department needs the bank account id and years of service fields only.
I think I need to have another table, but I don't know how will it look like.
How can I make the table flexible in a way that it can be extended based on the needs?
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm trying to make a application for keeping attendance for a relative's martial arts studio. I've tried looking around for some similar examples, but I couldn't find any specific or clear enough ones for this kind of application.
At the moment, I am using two tables, one for keeping student information, students(id, first_name, last_name, email, ...), and another table for attendance by the weeks in a year, attendance(id, week_1, week_2, week_3, ...). I am trying to change it to keep attendance by days instead, but can't seem to think of a good approach since I'm still kind of new to MySQL.
I am trying to make it so it is possible to see the attendance in a calendar-like format. It probably would be bad to just make columns for 365 days... and same with having a table for each month. I've noticed some similar applications just keep track of the dates, and store that in the database. Would this approach be better? Or, is there some other better approach to designing this kind of database? Thanks in advance.
In martial arts, instructors are students too -- so the Instructor table is sub-typed to the Student table. All common fields are in the Student table and only columns specific to instructors are in the Instructor table.
The Art table has list of arts that the school offers (judo, karate ...).
The school may have several rooms, these are listed in the Room table.
ClassSchedule describes the published schedule of classes that the school offers.
Attendance is captured in the Attendance table.
One row in the Calendar table is one calendar day (date). The table has date-properties like DayOfWeek, MonthName, MonthNumberInYear etc.
One row in the TimeTable is one minute of a day, like 7:05.
Calendar and TimeTable allow for easy attendance reporting by date/time, for example
-- Attendance of judo morning classes
-- for the first three months of the year 2010
-- by day of a week (Sun, Mon, Tue, ..)
select
DayOfWeek
, count(1) as Students
from ClassSchedule as a
join Calendar as b on b.CalendarId = a.CalendarId
join TimeTable as c on c.TimeID = a.StartTimeId
join Attendance as d on d.ClassId = a.ClassID
join Art as e on e.ArtId = a.ArtID
where ArtName = 'judo'
and Year = 2010
and MonthNumberInYear between 1 and 3
and PartOfDay = 'morning'
group by DayOfWeek ;
Hope this gets you started.
Attendance should have id, student_id and date. This is all you need to record when students attended. if you want to know how many students attended on a specific date (and who) you run a query for that specific date or date range.
You could also create a lesson table, in which case the attendance table would be
id, student_id and lesson_id
the lesson table could be
id, held_on_date
unless you need to add more columns to the lesson table, I think it is overkill.
Step back a little, you have two types of entities:
a person [like a student]
events [like a class]
Think of any entity as something that exists in the real world.
And one relationship
attendance
A relationship is just that, an association between entities, and often has time data associated with it or other types of measures.
So without thinking too hard, you should have 3 database tables:
attendee [E]
class [E]
attendance [R]
E = entity, R = relationship
If you find yourself duplicating data in one of the entity tables, this is a good sign that this entity requires a "sub-model". In some places this is called "don't repeat yourself" or DRY and for entity relational modeling, this is called "data normalization".
Remember, there's overhead in both time and code to build a more elaborate schema. So consider starting simple [3 tables] and refactoring away redundancy.