How to replace the column value with value from other connected table - sql

The code below is my query code of postgresql schema views.
Please assuming this a library table, which is a book list and you have some defined tags can apply on the book itself, and every book will be devided into one category.
CREATE VIEW tagging_books AS
SELECT tags."TagName", books."BookISBN", books."BookName", books."BookCategoryID"
FROM library
INNER JOIN tags on library."TagName_id" = tags."id"
INNER JOIN books on library."BookISBN_id" = books."id"
ORDER BY tags."id"
The schema views inside db will looks like this:
/tags.TagName /books.BookISBN /books.BookName /books.BookCategoryID
Python ISBN 957-208-570-0 Learn Python 1
And the BookCategoryID from table "books" is actually a foreign key of table "category", the table looks like this:
/category
BookCategoryID CategoryName
1 Toolbook
I wonder that, is there anyway to replace the books."BookCategoryID" field to category."CategoryName" by query code? Like the example below.
/tags.TagName /books.BookISBN /books.BookName /category.CategoryName
Python ISBN 957-208-570-0 Learn Python Toolbook
Since they are connected with each other, I think they can definitely being replaced, but I don't know how to do... Thank you.

To include category.name, simply join with table category on the foreign-key constraint like:
select category.name, books.*
from books
join category on books.BookCategoryID = category.BookCategoryID
You can add it to your view creation as well:
CREATE VIEW tagging_books AS
SELECT tags.TagName, books.BookISBN, books.BookName, category.name as "CategoryName"
FROM library
JOIN tags on library.TagName_id = tags.id
JOIN books on library.BookISBN_id = books.id
JOIN category on books.BookCategoryID = category.BookCategoryID
ORDER BY tags.id

Related

DQL relation Many to Many with Symfony

I would like to SELECT the categories in my table product_category through the table categories.
I have a FK many to many between product and category so the table product_category has been created dynamically.
I found that code for get the information in the other table when the FK is not directly in the table I am :
->join(ProductComponentSupplier::class, "pcs", \Doctrine\ORM\Query\Expr\Join::WITH, "p.id = pcs.product")
But in this case, ProductComponentSupplier is a class so it's accessible that way.
I would like to know if there is a way in DQL to get the information or I have to use SQL.
In SQL would be :
SELECT *
FROM category
LEFT JOIN product_category ON category.id = product_category.category_id
I hope I was clear.
Thank you so much for your help.

How can I take a joined table and use it to reference another table?

I've just started learning SQL and need help with an assignment question. I am asked to look through a dataset about Kickstarter campaigns. I'm asked to find the top 3 categories by amount of backers.
Here is the ER diagram:
ER diagram
In the 'Campaign' Table, there's the 'backers' column, but the 'Category' Table is only related with the Campaign through the 'Sub-Category' Table.
So far, I have been able to Join sub_category.category_id with the sub-category.category_name, but i'm not sure how to take this new Table and join it with Campaign
SELECT C.name AS category_name, SC.category_id, SC.id AS SC_id
FROM Category AS C
JOIN sub_category AS SC ON C.id = SC.category_id
Screenshot
I am hoping to have a table where there is a column for 'Category Name' and 'Backers' and then simply sort it by the number of backers
How should I go about this? Am I on the right track?
SELECT C.name AS category_name, CA.backers
FROM campaign AS CA
JOIN sub_category AS SC
ON CA.sub_category_id =SC.Id
JOIN Category AS C
ON C.id = SC.category_id
order by CA.backers
You can have multiple joins all together in one query.
Secondly there is a connection between Campaign and Sub_Category table which will help to join these two tables.
Later we can then join Category table as these two table has a connection between them based on Category_Id which is a foreign key in sub category table.
At last you can just order by based on Backers.
Let me know if you have any issue or doubt in comments.
And just to take Magnus's answer and rewrite visually, you can better see the hierarchy of the query. See how it closely resembles that of your table relationships
SELECT
C.name category_name,
CA.backers
FROM
campaign CA
JOIN sub_category SC
ON CA.sub_category_id = SC.Id
JOIN Category C
ON SC.category_id = C.id
order by
CA.backers
Notice the indentation to the table its ID is based upon from that prior to it. This way you know which column FROM connecting TO. I have found that if you list the tables in the FROM clause first to show all the HOW tables are related and ON what foreign : primary key relationships, that is the hardest part. Then its just pulling the columns you want after that.

Joining three tables. Two related, and one unrelated to the other two

I want to Create a view called ShowAllBooksBorrowed that shows the information (BookName, ISBN, BookCategoryName, BookAuthor, BorrowedDate, ReturnDate, ActualReturnDate) of all the books that have been borrowed from the library but not returned.
I am having trouble figuring out how to relate the BorrowerInfo table to the BookInfo and BookCategory table using the information from the Books table. I understand how it relates but I am not sure how to carry this out. I think I may need to use Union or CrossJoin?
here is my database:
You could create a view like as shown below:
create view show_all_books_borrowed as
select
k.bookname,
b.isbn,
c.bookcategoryname,
k.bookauthor,
w.borrowdate,
w.returndate,
w.actualreturndate
from books b
join borrowerinfo w on w.bookid = b.bookid
join bookinfo k on k.isbn = b.isbn
join bookcategory c on k.bookcategoryid = c.bookcategoryid
where w.actualreturndate is null

"Tag" searching/exclusion query design issue

Background: I'm working on a homebrew project for managing a collection of my own images, and have been trying to implement a tag-based search so I can easily sift through them.
Right now, I'm working with RedBean's tagging API for applying tags to each image's database entry, however I'm stuck on a specific detail of my implementation; currently, to allow search of tags where multiple tags will refine the search (when searching for "ABC XYZ", tagged image must have tags "ABC" and "XYZ"),
I'm having to handle some of the processing in the server-side language and not SQL, and then run an (optional) second query to verify that any returned images don't have a tag that has been explicitly excluded from results. (when searching for "ABC -XYZ", tagged image must have tag "ABC" and not "XYZ").
The problem here is that my current method requires that I run all results by my server-side code, and makes any attempts at sensible pagination/result offsets inaccurate.
My goal is to just grab the rows of the post table that contain the requested tags (and not contain any excluded tags) with one query, and still be able to use LIMIT/OFFSET arguments for my query to obtain reasonably paginated results.
Table schemas is as follows:
Table "post"
Columns:
id (PRIMARY KEY for post table)
(image metadata, not relevant to tag search)
Table "tag"
Columns:
id (PRIMARY KEY for tag table)
title (string of varying length - assume varchar(255))
Table "post_tag"
Columns:
id (PRIMARY KEY for post_tag table)
post_id (associated with column "post.id")
tag_id (associated with column "tag.id")
If possible, I'd like to also be able to have WHERE conditions specific to post table columns as well.
What should I be using for query structure? I've been playing with left joins but haven't been able to get the exact structure I need to solve this.
Here is the basic idea:
The LEFT OUTER JOIN is the set of posts that match tags you want to exclude. The final WHERE clause in the query makes sure that none of these posts match the entries in the first post table.
The INNER JOIN is the set of posts that match all of the tags. Note that the number two must match the number of unique tag names that you provide in the IN clause.
select p.*
from post p
left outer join (
select pt.post_id
from post_tag pt
inner join tag t on pt.tag_id = t.id
where t.title in ('UVW', 'XYZ')
) notag on p.id = notag.post_id
inner join (
select pt.post_id
from post_tag pt
inner join tag t on pt.tag_id = t.id
where t.title in ('ABC', 'DEF')
group by pt.post_id
having count(distinct t.title) = 2
) yestag on p.id = yestag.post_id
where notag.post_id is null
--add additional WHERE filters here as needed

How to write a SQL statement which gets results via a relationship table? (many to many)

I have 3 tables (archive has many sections, section (may) belong to many archives):
archive
id PK
description
archive_to_section
archive_id PK FK
section_id PK FK
section
id PK
description
What would the SQL look like to list all the sections that belong a certain archive id?
I am just learning SQL. From what I've read it sounds like I would need a join, or union? FYI I'm using postgres.
[Edit] This is the answer from gdean2323 written without aliases:
SELECT section.*
FROM section
INNER JOIN archive_to_section
ON section.id = archive_to_section.section_id
WHERE archive_to_section.archive_id = $this_archive_id
SELECT s.*
FROM section s INNER JOIN archive_to_section ats ON s.id = ats.section_id
WHERE ats.archive_id = 1
SELECT s.*
FROM archive_to_section ats
INNER JOIN section s ON s.id=ats.section_id
WHERE ats.archive_id= #archiveID