This relates to a post I made here
where initially I was interested in WordPress taxonomies
, but the more I think about my case, the more I think a custom table
approach makes sense.
So I am curious if there are any database experts who can advise me on table structure given my scenario:
I am setting up my site so I can teach guitar courses
. Perhaps of importance, I will not have many courses. Maybe 4-8.
Under a given course
, I have
Course 1
Lesson 1.1
Topic 1.1.1
Quiz 1.1.1.1
Quiz 1.1.1.2
Forum Topic 1.1.1.1
Topic 1.1.2
Quiz 1.1.2.1
Exercise 1.1.2.1
etc
Course 2
Lesson 2.1
Topic 2.1.1
Quiz 2.1.1.1
Forum Topic 2.1.1.1
Topic 2.1.2
etc
etc
I also use a course forum (BBPress
, which has its own taxonomy system), and at times need to tie individual forum topics to lesson topics.
The types of queries I need to do are
- Get me all lessons for a course
- Get me all topics for a lesson
- Get me all quizzes for a topic
- Get me all quizzes for a lesson (which means quizzes under topics for the lesson)
- Get me all quizzes for a course (which means all quizzes across all topics in the course)
- Same above like quizzes, but for forum topics
You probably get the idea.
Here is example dataset:
CREATE TABLE `posts` (
`ID` bigint(20) UNSIGNED NOT NULL,
`post_title` text COLLATE utf8mb4_unicode_520_ci NOT NULL,
`post_parent` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
`post_type` varchar(20) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT 'post'
) ;
INSERT INTO posts
(ID, post_type, post_title, post_parent)
VALUES
(1, 'course', 'Course 1', 0),
(2, 'lesson', 'Lesson 1.1', 0),
(3, 'course-topic', 'Topic 1.1.1', 0),
(4, 'quiz', 'Quiz 1.1.1.1', 0),
(5, 'quiz', 'Quiz 1.1.1.2', 0),
(6, 'quiz', 'Quiz 1.1.1.3', 0),
(7, 'course-topic', 'Assignment 1.1.1.1', 0),
(8, 'forum', 'Course 1 Forum', 0),
(9, 'forum', 'Course 1 Discussions', 8),
(10, 'topic', 'Discussion 1.1.1.1', 9),
(11, 'course-topic', 'Topic 1.1.2', 0),
(12, 'quiz', 'Quiz 1.1.2.1', 0),
(13, 'lesson', 'Lesson 1.2', 0),
(14, 'course-topic', 'Topic 1.2.1', 0),
(15, 'topic', 'Discussion 1.2.1.1', 9);
Initially I set up taxonomy tables in WordPress and made a sqlfiddle with some example data and some example queries.
Here is the fiddle:
http://sqlfiddle.com/#!9/ffa734/3
A query just to get lessons for a given course ID involves 4 tables and looks like
-- get all lessons for a given course
SELECT course_rels.object_id as course_id, lesson.post_title as lesson_title FROM posts AS lesson
INNER JOIN wp_term_relationships AS lesson_rels ON lesson.ID = lesson_rels.object_id
INNER JOIN wp_term_relationships AS course_rels ON course_rels.object_id = 1
INNER JOIN wp_term_taxonomy AS lesson_tax
ON
(lesson_tax.term_taxonomy_id = lesson_rels.term_taxonomy_id
AND
lesson_tax.parent = course_rels.term_taxonomy_id)
INNER JOIN wp_terms AS terms ON terms.term_id = lesson_tax.term_id
WHERE terms.name = 'Lesson';
After I realized how awkward the queries become using taxonomies, I decided to make a custom table which given post data above, would look like
CREATE TABLE `relations` (
`post_id` bigint(20) UNSIGNED NOT NULL,
`related_course` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
`related_lesson` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
`related_topic` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
`post_type` varchar(16) COLLATE utf8mb4_unicode_520_ci NOT NULL DEFAULT ''
);
INSERT INTO relations
(post_id, related_course, related_lesson, related_topic, post_type)
VALUES
(1, 0, 0, 0, 'course'),
(2, 1, 0, 0, 'lesson'),
(3, 1, 2, 0, 'lesson-topic'),
(4, 1, 2, 3, 'quiz'),
(5, 1, 2, 3, 'quiz'),
(6, 1, 2, 3, 'quiz'),
(7, 1, 2, 0, 'lesson-topic'),
(8, 1, 0, 0, 'forum'),
(9, 1, 0, 0, 'forum'),
(10, 1, 2, 3, 'topic'),
(11, 1, 2, 0, 'lesson-topic'),
(12, 1, 2, 11, 'quiz'),
(13, 1, 0, 0, 'lesson'),
(14, 1, 13, 0, 'lesson-topic'),
(15, 1, 13, 14, 'topic');
So you see in the fiddle examples of taxonomy queries, and example of a query I can do with a custom table.
The thing is, I have no expertise whatsoever in databases. I have no idea if my custom table approach is just a disaster waiting to happen. I don't want to reinvent anything - I am just tired of WordPress's approach of lumping data together and forcing me to query among tons of rows that are of no importance to my query of interest.
Given how often people have to solve this sort of problem, is there a tried and true, efficient, scalable approach to let me extract the sort of relational data I mention above?
I will add to the fiddle any other proposed solutions that come about here. I guess ideally I would have to insert thousands of rows into all tables to really see how queries perform, but maybe some expert immediately sees an optimal approach?
The biggest pitfall I see with my custom table is that it gives no flexibility given the column names I have chosen. If that is really a terrible approach, then maybe I just go with WordPress's taxonomies...