Reputation: 312
I'm trying to join multiple tables(BooksReview
, Followers
, Books
) with Users
table which the Books
references userId
from Users
, BooksReview
references userId
which is the userId
who reviewed a book and references bookId
from Books
which is the book id that been reviewed on and last but not least the Followers
table(and here I think where the problem is) has two references from the same primary key it has follower
from userId
in Users
table and followed
also from userId
in Users
table.
The Problem: I created a MySQL query to fetch the number of books reviews for specific book based on specific user, and to fetch number of books for this user and the number of followers he/she has, but when I added the Followers
join part to my query it shows 0 result for all values which the expected values are 4 books, 4 reviews, and 1 follower.
I have tried to change the join types in the query but it endup with the same result and searched joining two foregin keys in the same table for the same primary key but I didn't find anything useful.
```
CREATE TABLE IF NOT EXISTS `Authors`.`Users` (
`userId` VARCHAR(100) NOT NULL,
`username` VARCHAR(25) NOT NULL,
`password` VARCHAR(16) NOT NULL,
`email` VARCHAR(254) NOT NULL,
`birthday` DATE NULL,
`aboutMe` TEXT(300) NOT NULL,
`facebookAccount` VARCHAR(25) NULL,
`twitterAccount` VARCHAR(25) NULL,
`linkedinAccount` VARCHAR(25) NULL,
`profileImage` VARCHAR(200) NULL,
PRIMARY KEY (`userId`),
UNIQUE INDEX `username_UNIQUE` (`username` ASC),
UNIQUE INDEX `email_UNIQUE` (`email` ASC))
ENGINE = InnoDB;
```
CREATE TABLE IF NOT EXISTS `Authors`.`Books` (
`bookId` VARCHAR(100) NOT NULL,
`bookCategory` VARCHAR(25) NOT NULL,
`title` VARCHAR(25) NOT NULL,
`bookCover` VARCHAR(45) NOT NULL,
`bookDescription` VARCHAR(200) NOT NULL,
`userId` VARCHAR(100) NOT NULL,
`price` DECIMAL(2,2) NOT NULL,
`introduction` VARCHAR(300) NOT NULL,
PRIMARY KEY (`bookId`),
INDEX `userId_idx` (`userId` ASC),
CONSTRAINT `userId`
FOREIGN KEY (`userId`)
REFERENCES `Authors`.`Users` (`userId`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
```
```
CREATE TABLE IF NOT EXISTS `Authors`.`BooksReview` (
`bookId` VARCHAR(100) NOT NULL,
`rateMessage` VARCHAR(100) NULL,
`rateNumber` DECIMAL(1,1) NULL,
`userId` VARCHAR(100) NOT NULL,
INDEX `userId_idx` (`userId` ASC),
CONSTRAINT `bookId`
FOREIGN KEY (`bookId`)
REFERENCES `Authors`.`Books` (`bookId`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `userId`
FOREIGN KEY (`userId`)
REFERENCES `Authors`.`Users` (`userId`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
```
CREATE TABLE IF NOT EXISTS `Authors`.`Followers` (
`follower` VARCHAR(100) NOT NULL,
`followed` VARCHAR(100) NOT NULL,
INDEX `follower_idx` (`follower` ASC),
INDEX `followed_idx` (`followed` ASC),
CONSTRAINT `follower`
FOREIGN KEY (`follower`)
REFERENCES `Authors`.`Users` (`userId`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `followed`
FOREIGN KEY (`followed`)
REFERENCES `Authors`.`Users` (`userId`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB;
THIS IS THE QUERY
SELECT count(br.bookId) AS reviewsCount, count(b.bookId) AS booksCount, count(f.follower) AS followersCount
FROM Users AS u
LEFT JOIN Books AS b ON b.userId = u.userId
JOIN Followers AS f ON b.userId = f.followed AND f.follower = u.userId
INNER JOIN BooksReview AS br ON br.bookId = b.bookId
AND b.bookId IN (SELECT bookId
FROM Books
WHERE userId = 'dbb21849-ccce-4af1-aa0f-6653919bf956');
I expect the result should be 1 follower, 4 books and 4 reviews but the actual result is 0's for all.
DML:
Users
->
userId: dbb21849-ccce-4af1-aa0f-6653919bf956
username: mostafabbbaron
etc...
Books
->
userId: dbb21849-ccce-4af1-aa0f-6653919bf956
bookId: 5f39c1ae-5e99-4b3a-8ee0-97a80c1ba9b1
etc...
Followers
->
follower: dbb21849-ccce-4af1-aa0f-6653919bf956
folllowed: b39c8e0c-4124-4339-8c30-e1fc8db5f2d4
etc...
BooksReviews
->
userId: dbb21849-ccce-4af1-aa0f-6653919bf956
bookId: aa44a455-dc28-476f-b4b9-47563a717f03
etc...
Upvotes: 0
Views: 62
Reputation: 31772
Your query is wrong either way. But the reason for getting zeros as result are probably these conditions: b.userId = u.userId
and b.userId = f.followed AND f.follower = u.userId
.
IF b.userId = u.userId
and b.userId = f.followed
then f.followed = u.userId
IF f.followed = u.userId
and f.follower = u.userId
then f.followed = f.follower
That means that the user must follow himself/herself, which I doubt is the case.
I would write the query the following way:
SELECT
count(DISTINCT b.bookId) AS booksCount,
count(br.bookId) AS reviewsCount,
(SELECT COUNT(*) FROM Followers AS f WHERE f.followed = u.userId) AS followersCount
FROM Users AS u
LEFT JOIN Books AS b ON b.userId = u.userId
LEFT JOIN BooksReview AS br ON br.bookId = b.bookId
WHERE u.userId = 'dbb21849-ccce-4af1-aa0f-6653919bf956'
Note: While it's fine to have Users LEFT JOIN Books LEFT JOIN BooksReview
, because you have a "relation chain" Users <- Books <- BooksReview
. But you shouldn't just JOIN the Followers
table, because it's not really related to Books
or BooksReview
, and doesn't fit into that chain. That is why I used a subquery in the SELECT clause, to count the followers.
Upvotes: 2