Making sense of database table references with foreign and primary keys - sql

I am relatively new to database logic, and am trying to figure out how multiple tables should/shouldn't reference each other.
I have a table, 'Book', that should have columns:
| 'title' | 'genre' | 'author' | 'buyOption' | 'pubDate'
I want each book to have the possibility to have 1 or more genres.
I want each book to have the possibility to have 1 or more authors.
I want each book to have the possibility to have 1 or more purchase options ('buyOption').
and each purchase option (Amazon, Walmart, etc.) for each book has a unique url.
What I think makes sense (please correct me where I'm wrong):
__________________________
| |
| Book |
|________________________|
|Primary Key | book_id | //seems redundant (same as title_id)...would like to just use title_id, but idk if that's possible
|------------|-----------|
|Foreign Key | title_id | <--------------------------------------------|
|Foreign Key | bo_id | <----------------------------------| |
|Foreign Key | genre_id | <--------------------------| | |
|Foreign Key | author_id | <-------------------| | | |
| - - - - - | - - - - - | | | | |
| | pubDate | //publish date | | | |
|________________________| | | | |
| | | |
| | | |
| | | |
__________________________ | | | |
| | | | | |
| Authors | | | | |
|________________________| | | | |
|Primary Key | author_id |------------------| | | |
|------------|-----------| | | |
|--->|Foreign Key | title_id | | | |
| | - - - - - | - - - - - | | | |
| | | author | | | |
| |____________|___________| | | |
| | | |
| | | |
| __________________________ | | |
| | | | | |
| | Genres | | | |
| |________________________| | | |
| |Primary Key | genre_id |-------------------------| | |
| |------------|-----------| | |
|--->|Foreign Key | title_id | | |
| | - - - - - | - - - - - | | |
| | | genre | | |
| |____________|___________| | |
| | |
| __________________________ | |
| | | | |
| | Buy Options | | |
| |________________________| | |
| |Primary Key | bo_id |---------------------------------| |
| |------------|-----------| |
|--->|Foreign Key | title_id | |
| | - - - - - | - - - - - | |
| | | buyBrand | //(Walmart, Amazon, etc.) |
| | | buyUrl | //(ex: https://www.amzn.com/buyBook1) |
| |____________|___________| |
| |
| |
| |
| __________________________ |
| | | |
| | Title | |
| |________________________| |
|---------|Primary Key | title_id |--------------------------------------|
|------------|-----------|
| | title |
|____________|___________|
Does it make sense to have the title table? If so, can i use its primary key to fill various other tables, as depicted?
If the 'Buy Options' table is going to have a bunch of different options and associated urls for each book, will it be possible to get the buyBrand and buyUrl directly from the main 'Book' table? In the end, I just want a giant table that I can grab cell data from. Right now I'm trying to figure out how to populate tables with my data, and what tables to fill for each piece of data.
(again, I'm new to database logic, so I apologize if my wording is hard to understand)

Your design does not look good. You are describing many-to-many relationships between books and genres, books and authors, books and options.
Storing references to the related genre, author, and option in the books table is not the right way to go: you can only store one related value per book (one genre, one author, one option), while you need many. Instead, for each of these relationships, you should have a separate table, called a bridge table, that references the associations.
On the other hand, information that is dependent on the book (say, the title) should be stored in the book table.
Here is one example for books and genres:
create table books(
book_id int primary key,
title varchar(100), --dependent column
pub_date date --dependent column
);
create table genres(
genre_id int primary key,
name varchar(100)
);
create table book_genres(
book_id int references book(book_id),
genre_id int references genre(genre_id),
primary key (book_id, genre_id)
);
Now, say you want to list all books that belong to genre 'Sci-Fi'; you would go:
select b.*
from books b
inner join book_genres bg on bg.book_id = b.book_id
inner join genres g on g.genre_id = bg.genre_id
where g.name = 'Sci-Fi'
The same logic should be implemented for each and every many-to-many relationship in your schema.

Related

Foreign Keys: Multiple Numeric or Character

I have to store records in a "Analyze" table which are referenced to a Object with a defined Id (nvarchar20).
I came up with two possible designs (see Option A or B) for the Analyze Table:
What I'm not sure about is weather its better to store the primary key of the different objects (ObjectA, ObjectB, ...) in separate columns or simply store the plain ObjectId
The Analyze Table is growing very fast and most operations are read via a given ObjectId. So most cases you have a ObjectId and have to search the Analyze Table.
The pattern of the ObjectId is always the same: for example you can identify a given ObjectIds Type if you look at the eight to fourth last characters CA16834K23850001ABCD
0001 is always ObjectA
0002 is always ObjectB
ObjectA
| PK (bigInt) | ObjectId (nvarchar20) | otherfields |
| ------------| --------------------- | ------------|
| 1 | CA16834K23850001ABCD | .. |
| 2 | CA16834K23850001ABCE | .. |
ObjectB
| PK (bigInt) | ObjectId (nvarchar20) | otherfields |
| ----------- | --------------------- | ----------- |
| 1 | CA16834K23850002ABCD | .. |
| 2 | CA16834K23850002ABCE | .. |
Option A:
AnalyzeTable
| id (bigInt) | ObjA_PK (bigInt)| ObjB_PK (bigInt)| otherfields... |
| ----------- | --------------- | --------------- | -------------- |
| 1 | 1 | NULL | ... |
| 2 | NULL | 1 | ... |
Option B:
AnalyzeTable
| id (bigInt) | ObjectId (nvarchar20) | otherfields... |
| ----------- | --------------------------- | --------------- |
| 1 | CA16834K23850001ABCD | ... |
| 2 | CA16834K23850002ABCD | ... |
What is the better design for reading the AnalyzeTable. Since numeric indexes might be faster than an index on an nvarchar?

Designing a database for a workout tracker

I'm designing a database for a workout tracker app. Each user should be able to track multiple workouts (routines). A workout can have multiple exercises an exercise can be used in many workouts. Each exercise will have a specific track type (weight and reps, distance and time, only reps).
My tables so far:
| User | |
|------|-------|
| id | name |
| 1 | Ilka |
| 2 | James |
| Exercise | | |
|----------|---------------------|---------------|
| id | name | track_type_id |
| 1 | Barbell Bench Press | 1 |
| 2 | Squats | 1 |
| 3 | Deadlifts | 1 |
| 4 | Rowing Machine | 3 |
| Workout | | |
|---------|---------|-----------------|
| id | user_id | name |
| 1 | 1 | Chest & Triceps |
| 2 | 1 | Legs |
| Workout_Exerice (Junction table) | |
|-----------------|------------------|------------|
| id | exersice_id | workout_id |
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 4 | 1 |
| Workout_Sets | | | |
|--------------|---------------------|------|--------|
| id | workout_exersice_id | reps | weight |
| 1 | 1 | 12 | 120 |
| 2 | 1 | 10 | 120 |
| 3 | 1 | 8 | 120 |
| 4 | 2 | 10 | 220 |
| 5 | 3 | null | null |
| TrackType | |
|-----------|-----------------|
| id | name |
| 1 | Weight and Reps |
| 2 | Reps Only |
| 3 | Distance Time |
My issue is how to incorporate the TrackType table for each workout set, my first option was to create columns in the Workout_Sets table for each tracking type (weight and reps, distance and time, only reps) but that means for many rows I will have many nulls. Another option I thought was to use an EAV type table but I'm not sure. Also do you think my design is efficient (Over-normalization)?
I would say that the most efficient way is to have nulls in your table. The alternative would require you to split many of the category's into separate tables. Also a recommendation is that you start factoring a User ID table into your database
Your description states that “Each exercise will have a specific track type” suggesting a one-to-one relationship between Exercise and TrackType, and that the relationship is unchanging. As such, the exercise table should have a TrackType column.
I suspect, however, that your problem description may be lacking specificity, making it difficult to give you sound advice. For instance, if the TrackType can vary for any given exercise, your TrackType column may belong on the Workout_Sets table. If the relationship between TrackType and Exercise/Workout_Sets is many-to-many, then you will need another junction table.
Your question regarding “over-normalization” depends upon many factors that are specific to your solution. In general, I would say no - the degree of normalization appears to be appropriate.

ActiveJdbc unable to include the table

I have two tables orders and address
Order table
+----+----------------+-----------------------------------+--------------------------------------------------+
| id | trackingNumber | user_id (reference to user table) | receiverAddress_id (reference to address table ) |
+----+----------------+-----------------------------------+--------------------------------------------------+
| 1 | TRACK123 | 1 | 2 |
+----+----------------+-----------------------------------+--------------------------------------------------+
| | | | |
+----+----------------+-----------------------------------+--------------------------------------------------+
address table
+----+--------+--------------+--------------+
| id | name | addressLine1 | addressLine2 |
+----+--------+--------------+--------------+
| 1 | Mr.abc | qwertyuiop | qwertyuiop |
+----+--------+--------------+--------------+
| | | | |
+----+--------+--------------+--------------+
Need help in activeJdbc joining these two tables and get address as the children in JSON.
I have tried the relation annotatins however unable to get the desired result.
//sample code: not working
LazyList<Orders> order = Orders.find("id = 1").include(Addresses.class);
order.toJson(true);

Postgres key-value table, select values as columns

I have the following table:
+----+---------+-------+
| id | Key | Value |
+----+---------+-------+
| 1 | name | Bob |
| 1 | surname | Test |
| 1 | car | Tesla |
| 2 | name | Mark |
| 2 | cat | Bobby |
+----+---------+-------+
Key can hold basically anything. I would like to arrive at the following output:
+----+------+---------+-------+-------+
| id | name | surname | car | cat |
+----+------+---------+-------+-------+
| 1 | Bob | Test | Tesla | |
| 2 | Mark | | | Bobby |
+----+------+---------+-------+-------+
Then I would like to merge the output with another table (based on the id).
Is it possible to do, if I don't know what the Key column holds? Values there are dynamic.
Could you point me to the right direction?

SQL tables relationship and indexes

I want to have 2 tables SalesOrderHeader and SalesOrderLine with one to many relationship and also want to build indexes.
SalesOrderHeader table:
SalesOrderNumber
------------------
| |
| 1 |
| |
|----------------|
| |
| |
| 2 |
| |
| |
------------------
SalesOrderLine table:
SalesOrderNumber Line
-------------------------
| | 1 |
| 1 |------|
| | 2 |
|----------------|------|
| | 1 |
| |------|
| 2 | 2 |
| |------|
| | 3 |
-------------------------
Please advise how possible to build relatinships and indexes with these tables structure approach?
Create a foreign key
ALTER TABLE SalesOrderNumberLine
ADD FOREIGN KEY (SalesOrderNumberID) REFERENCES SalesOrderNumber (ID)
Afterwards create a nonclustered index on that column
CREATE NONCLUSTERED INDEX IX_SalesOrderNumberLine_SalesOrderNumberID
ON dbo.SalesOrderNumberLine(SalesOrderNumberID);