How to combine two databases? - sql

I am asking myself how to best define a new database given two databases.
I have the following two databases
Author where I save information about authors i.e. Name, Birthyear, Country, Genre etc.
Book where I save information about the book i.e. AuthorName, ReleaseYear, Pages etc
How do I create a new database with the full information about all books and the author? I.e. a Book_Complete Database which includes Author.Name, ReleaseYear,Pages, Genre,ReleaseYear and Author.Birthyear, Author.Country?

Better to go for a single database and having 2 tables in it like
Author Table
AuthorId (PK)
Name
Birthyear
Country
Genre
Book Table
BookId (PK)
AuthorId (FK)
ReleaseYear
Pages

If you have two tables in a database you can combine them using JOIN. Here is SQLite tutorial on how to use JOIN.
https://www.sqlitetutorial.net/sqlite-join/
On the information you provided I assume you can you columns Name in table Author, and AuthorName in table Book. You can try something like this
SELECT
A.Name,
B.ReleaseYear,
B.Pages,
B.Genre,
B.ReleaseYear,
A.Birthyear,
A.Country
FROM
Author A
LEFT JOIN Book B
ON A.Name = B.AuthorName

Basically, I have these create these two tables on my app and want to store the combined version on a server. Or would you suggest another approach?
Yes we would. You should have one table per entity, i.e. one for the authors and one for the books. Thus you don't store data redundantly (e.g. the author's name or the book's title), which could otherwise lead to inconsistencies later. You can read up on database normalization here: https://en.wikipedia.org/wiki/Database_normalization or google it.
Now you must decide how to link the tables. One author can write multiple books. Can one book be written by multiple authors? Give both tables IDs you can work with (or find some natural unique key, like the ISBN for the book and maybe name + birth year for the author - the name only will probably not suffice and maybe it won't even when combined with the year).
If one book can only be written by one author, you have a 1:n relation (one book written by one author, one author writing multiple books).
author (author_id, name, birth_year, country, ...)
book (book_id, title, author_id, release_year, pages, ...)
If one book can have several authors, you have an m:n relation (one book written by multiple authors, one author writing multiple books).
author (author_id, name, birth_year, country, ...)
book (book_id, title, release_year, pages, ...)
book_author (book_id, author_id)
You can always join the tables, so as to get a combined result.

Related

Filling in a database

Let's say we have a database with the following two tables: books and authors.
The authors table has columns: id, name.
The books table has columns: id, title, author_id (refers to the authors table).
I add new books into the database manually, but I'd like to write a simple sql script to automate this task. Can I avoid looking up author_id by author name in the authors table (can this step be done by a database)? What I want is to enter the book title and the author name (i.e. I don't want to do looking up author_id first), something like this:
//script.sql
INSERT "A quick guide to SQL", "Philip Collins"
You can use a SELECT statement together with an insert:
insert into books (title, author_id)
select 'A quick guide to SQL', a.id
from author a
where a.name = 'Philip Collins';
This assumes that the author name is unique, otherwise it will insert multiple rows into the books table.
Note that in SQL, string constants are enclosed in single quotes ('), double quotes (") are for identifiers.
You can create a view:
create view v_books as
select b.*, a.name
from books b join
authors a
on b.author_id = a.id;
This is a stored query and can be used like a table.

sqlplus DELETE statement

I'm using sqlplus (oracle). I trying to write a statement to remove all authors that have not yet published a book based on the bookauthor table.
Since I have joined to tables , I don't know how to delete authors that have not yet published a book. Also I'm not sure If I got subquery correctly in order to get an output of authors who have not published a book.
DELETE
FROM bookauthor, books
WHERE authorid =
(SELECT authorid, count(*) pubdate
FROM bookauthor
JOIN books USING (isbn)
GROUP BY authorid
HAVING count(*) < 1);
This is what I have so far.
I can't get it run correctly.
For table books -> isbn, title, pubdate, pubid, cost, retail, discount, category
for table bookauthor -> isbn, authorid
There are several flaws in your delete statement:
You want to delete authors that haven't published a book. That means you should be looking for authors that have no entry in the bookauthor table. But you don't even mention any author table and DELETE FROM bookauthor, books instead, which makes no sense.
You compare WHERE authorid = (SELECT authorid, count(*) FROM .... How can one ID possibly equal a pair of ID and count? It would have to be WHERE authorid = (SELECT authorid FROM ... instead.
In your subquery you are asking for HAVING count(*) < 1. But every author that is in the table occurs at least once of course. So this condition is never met. You are kind of asking: "Which of the authors in the bookauthor table is not in the bookauthor table?".
As mentioned, all this only makes sense with an author table:
trying to write a statement to remove all authors that ...
You are showing two tables. The book table where each book is identified by its ISBN. And the bookauthor table that links books to authors. This is called a bridge table (or junction table or association table or ... &dash; well there are many names for this). It establishes an m:n relation between author and book, so one author can have many books and one book can be written by more than one author. (If you wanted an 1:n relation instead, so that a book can only be written by one author, then the author ID would be an attribute in the book table.) So there must be an author table you haven't shown that the bookauthor table is referring to.
It should be something like:
delete from author where authorid not in (select authorid from bookauthor);
DELETE
FROM bookauthor
WHERE authorid =
(SELECT authorid FROM bookauthor WHERE isbn NOT IN (SELECT isbn FROM books))
Try this.
DELETE
FROM bookauthor
WHERE authorid =
(SELECT authorid FROM bookauthor a LEFT OUTER JOIN books b ON a.isbn = b.isbn WHERE b.isbn IS null)
Or this.

SQL multiplicity many to many insertion process

my question it seems to be pretty simple but unfortunately i couldn't find any satisfactory answer for this.
Please take a look on the following example:
Table Author define a author, Document has at least one author and table Authors group all authors that a document has.
My question is: Each time that i insert a document i need to verify if my group of authors exists already on table Authors.
What is the best way to do this?
I suppose that in first place i will need to verify if this group already exist and then, i should get that id (if already exist) or generate a new record on Authors (if group doesn't exist).
Question:
Is this the correct logic process that should occur on tables that has a multiplicity of many to many?
How can i check if a group of values already exist on table Authors??
There is something like this select * from Authors where a_id IN(1,2,3) but in a exclusive way. :S
Any help would be great.
Thanks
I would rather go with a solution with three tables:
Author
Document
rel_author_document
And rel_author_document will have a structure like:
author_fk
document_fk
You don't need to add a new group, but just to associate authors to a document.
In rel_author_document you can even add additional columns like role, if you need something like that.
With this approach you can have two documents with the same group of authors, but this won't kill you performances.
In case your question is for a homework assignment and you can't change table structure then:
Query the Authors table to see if you have a group of Author with the same number of author_id in the where condition, something like:
select count(1) cnt
from Authors
where a_id IN(1,2,3)
If cnt is different from the number of author_ids, then insert a new group
If cnt is equal then get the id of that group of Authors:
select ID
from Authors
where a_id = 1
or a_id = 2
or a_id = 3
group by 1
having count(1) = 3
If its a "many-to-many" relationship I believe the table structure you are looking for is:
Author (
a_id,
name,
birth_date,
domain)
Document (
d_id,
abstract,
year)
Auth_Doc (
a_id,
d_id
)
In terms of checking if there is already a group of authors, it depends n how you're displaying your data. If I was uploading a document and I wanted to check if a set of authors exist, I would do the following:
Say your data is stored as:
a_id | name
1 | john, jack, bob
SELECT * FROM Author WHERE name like '%john%'
I hope this helps,
Sohail

SQL movie database diagram

Im working on a small school project where im creating a movie database in SQL. I've created the tables and was wondering if I will encounter any problems with the model i created.
Thanks in advance.
Current diagram
Edit:
Here is the new diagram
MovieDetails is bad design. You need one row in MovieDetails per actor, while the director will be the same, which is data duplication. Instead, the Movie table should have a foreign key referencing director, then a MovieActor table should represent the many to many relationship between movies and actors.
Technically, there's also no reason to have different tables for Directors and Actors since you have the same data in the tables. You could just as well have a Person table with both.
How about (I am only showing the relevant columns)
movie table
-----------
id
title
person
------
id
name
cast table
----------
movie_id
person_id
movie_role_id (actor, director, ...)
role_type table
----------------
id
name (actor, director, ...)
genres table
------------
id
name
movie_genres table
------------------
movie_id
genre_id
I would consider the following structure:
movie(id, title, year, rating, plot, length)
actor(id, first name, last name, nationality, birth_date)
director(id, first name, last name, nationality, birth_date)
movie_x_actor(movie_id, actor_id)
movie_x_director(movie_id, director_id)
This is, of course, just the simplest example.
You can, for instance add a movie_series table like:
movie_series(id, title)
movie_x_movie_series(movie_id, series_id, plot_order_number)
and, like #Juergen described, a movie usually belongs to more than one genre so:
genres(id, genre_name, genre_description)
movie_x_genres(movie_id, genre_id)
You should definitely take a look at one-to-many and many-to-many relationships between rows in tables.
Cheers

Create a relation

I have no idea about how to create relation and solve their queries. I want to relation as follows:
BookAuthor(book, author, earnings)
BookReference(book, referenceBook, times)
BookReview(book, reviewer, score)
BookPublih(book, year, publisher, price, numbar)
In these database, each book may have 1 or more authors & each author may make a diff. amt. of money from that book. One book may make reference to other book.1 book may be reviewed by diff. reviewers and get diff. scores. an author could also be a reviewer & a publisher.
I want to solve following queries
Find all books published in 2003 & reviewed by both Sammer Tulpule & Hemant Mehta.
Find all the reviewers who never reviewed their own books.
Find all authors who reviewed more than 2 books written by Sita Mitra.
Find all authors who have written exactly 1 book and reviewed more than 1 book.
Find all the reviewer who reviewed every book from 'Stephen King'.
Find all books published in 1995-2000 in descending order.
I know, these is not good to find an answer, but believe me i really don't under
A solution to your problem could use these tables:
BOOKS (BookID, BookName,PubDate,PublisherPerson_ID,Price,Number) //stores each book and its data
PERSONS(PersonID, Name) //stores any people (authors, reviewers)
BOOKAUTHORS(Book_ID, Person_ID) //many to many relationship between books and authors
BOOKREVENUE(Book_ID, Person_ID, Revenue) //stores revenue for each book per author
BOOKREFERENCES(Book_ID, RefBook_ID) //many to many reference table for books
BOOKREVIEWERS(Book_ID, Person_ID, Score) //many to many relationship for book reviews
Im not going to write the queries here, but this will get you started