How would I do a join of three tables with sql server - sql

I'm trying to figure out what to do here. Look at these tables:
users
id, username, password
books
id, title
users_books
bookID, userID
How would one join these together? If I for example wanted to see user 47's books?

Well, if it is a homework then instead of giving fish everyday, teaching how to fish would be more helpful.
I hope the following references would aid in understanding SQL joins-
http://www.sql-tutorial.net/SQL-JOIN.asp
http://www.tizag.com/sqlTutorial/sqljoin.php
As far as your join query is concerned, response given by 'm-sharp' should give you the correct answer.
cheers

If you are using SQL Server, this query should work.
select books.title
from books, users_books
where books.id = users_books.bookID and users_books.id = 47

select b.title from users_books ub
join books b on b.id = ub.bookID
where ub.userID = 47

Since none of the other answers are joining three tables (your question heading states three but your body only needs two), I'll give you a three table version.
To do that I assume you have the username of the user rather than the ID. In that case, you can do:
select
u.id as user_id,
u.username as user_name,
b.id as book_id,
b.title as book_title
from
users u,
books b.
user_books ub
where u.username = 'username-of-user-47'
and u.id = ub.userID
and b.id = ub.bookID
This sort of thing can also be done with explicit JOINs but I prefer the "old school" SQL ways especially when the DBMS is clever enough to optimize it in the same manner, such as my beloved DB2/z :-)

Related

Counting positions in a row oracle

I'm making bookstore database and in the table "Authors" I've got column where i'd like to count books written by author in the table "Books". Table "Books" has foreign key "id_author". I have no idea how to do it, it's something like
SELECT COUNT(*) FROM Books WHERE id_author = "id of chosen author"
What to write in code in place of "id of chosen author"?
How to put it in a row in table "Author"?
You could join on the authors table and query by its columns (e.g., the first and last name):
SELECT COUNT(*)
FROM books b
JOIN author a ON b.id_author = a.id
WHERE a.firstname = 'John' AND a.lastname = 'Doe'
Depending on the application you have, the application might already have the author id. This means that you could just do a
SELECT COUNT(*) FROM Books WHERE id_author = "id of author provided by application"
Although the difference is probably not large compared to Mureinik's answer, this can enhance your performance on large databases as you do not have to do the join between author and book table.
Number of books by author:
select a.author, count(1)
from author a
join books b
on a.id = b.id_author
group by a.author

Select a user by their username and then select data from another table using their UID

Sorry if that title is a bit convoluted... I'm spoiled by an ORM usually and my raw SQL skills are really poor, apparently.
I'm writing an application that links to a vBulletin forum. Users authenticate with their forum username, and the query for that is simple (selecting by username from the users table). The next half of it is more complex. There's also a subscriptions table that has a timestamp in it, but the primary key for these is a user id, not a username.
This is what I've worked out so far:
SELECT
forum.user.userid,
forum.user.usergroupid,
forum.user.password,
forum.user.salt,
forum.user.pmunread,
forum.subscriptionlog.expirydate
FROM
forum.user
JOIN forum.subscriptionlog
WHERE
forum.user.username LIKE 'SomeUSER'
Unfortunately this returns the entirety of the subscriptionlog table, which makes sense because there's no username field in it. Is it possible to grab the subscriptionlog row using the userid I get from forum.user.userid, or does this need to be split into two queries?
Thanks!
The issue is that you are blindly joining the two tables. You need to specify what column they are related by.
I think you want something like:
SELECT * FROM user u
INNER JOIN subscriptionlog sl ON u.id = sl.userid
WHERE u.username LIKE 'SomeUSER'
select * from user u JOIN subscriptions s ON u.id = s.id where u.username = 'someuser'
The bit in bold is what you want to add, it combines the 2 tables into one that you return results from.
try this
SELECT
forum.user.userid,
forum.user.usergroupid,
forum.user.password,
forum.user.salt,
forum.user.pmunread,
forum.subscriptionlog.expirydate
FROM
forum.user
INNER JOIN forum.subscriptionlog
ON forum.subscriptionlog.userid = forum.user.userid
WHERE
forum.user.username LIKE 'SomeUSER'

SQL, using data from a number of separate tables to receive an output

So my tables I'm working with look like the following:
Book(BookID, Title)
Author(BookID, AuthID)
Writer(AuthID, PubID, FirstName, LastName)
Publisher(PubID, PubName, Country)
And I'd love to change them to make more sense, but I'm not allowed to even change their names at this point.
Anyway, I have two separate pieces of code that I want to run together. So it's the result of this:
select Book.Title
from Book
join Author
on Book.BookID=Author.BookID
group by Book.Title, Book.BookID
having count(*) >= 2
with this:
select AuthorID
from Author
join Publisher
on Author.PubID=Publisher.Publisher
where Publisher.Country like 'Australia'
Initially I thought INTERSECT might work but I quickly realised that because they're not matching fields, I need something else. And the fact that Writer and Publisher have to be linked via Author is throwing me off completely.
Is there a way to do this save going back to the table and changing it to something less unnecessarily complex?
I've been going through the list of statements and whatnot on trying to find a solution, but I'm not sure which one I'm supposed to be looking at. Perhaps something with GROUP in it? So anything, just a point in the right direction would be much appreciated.
Are you trying to find all books with more than one author published in Australia?
If so, the query would look something like this:
select b.Title
from Book b join
Author a
on b.BookID = a.BookID join
Writer w
on w.AuthId = a.AuthId join
Publisher p
on w.PubId = p.PubId
where p.Country like 'Australia'
group by b.Title, b.BookID
having count(*) >= 2;
I think there's a small conceptual misunderstanding blocking your way here.
The two queries can be combined into a single query, and return the results you want, via multiple joins involving all these tables.

How do I establish a SQL query for this many-to-many table?

I'm building this bartering-type function in this site using PHP/MySQL and I'm trying to create a query that responds with the following fields:
owner's username, title, offerer's username, offerer's item
Basically I have three tables here with the following fields:
users
user_id, username, email
items_available
item_number, owner_id (foreign key that links to user_id), title
offers_open
trade_id, offerers_id (fk of user_id), offerers_item(fk with item_number), receivers_id (fk from user_id)
How do I do this? I've seen some references to many-to-many SQL queries but they don't seem to particularly fit what I'm looking for (for example, the offerers_id and the owner_ids refer to different users_id in the Users table, but how do I make them distinguishable in the sql query?)
If I understand correctly, this is what you are looking for:
SELECT owner.username, oferrers.username, ia.title
FROM offers_open o
INNER JOIN users AS offerers
ON o.offerers_id = offerers.user_id
INNER JOIN items_available AS ia
ON o.offerers_item= ia.item_number
INNER JOIN users AS owner
ON ia.owner_id = owner.user_id
I don't see a title on the users table, so didn't include one.
I'm not sure exactly what output you want, but since your users table will appear twice in the query, they need to be aliased like so:
SELECT offerer.username AS offerer_username, title, receiver.username AS receiver_username
FROM users AS owner
JOIN items_available ON owner_id = owner.user_id
JOIN offers_open ON offerers_item = item_number
JOIN users AS receiver ON receivers_id
Again, don't know if that's what you want, but hope you get the idea.
It sounds as you need an alias of the users table.
Something like?
select
u.*, ia.*, oo.*,u2.*
from
users as u,
items_available as ia,
offers_open as oo,
users as u2
where
u.user_id = ia_user_id and
oo.user_id = u2.user_id and
oo.item_id = ia.item_id

SQL SELECT complex expression in column - additional boolean

I seem to have reached a mental block on this and hope someone can give me a kick in the right direction.
I have a web application similar to a newsreader client. It's written in Python and uses SQLAlchemy but that's not important here as I'm trying to get my head around the SQL, also I'm using SQLite as a backend.
There is a Users table and an Articles table, the Users table is obvious enough and the Articles table stores individual articles (like posts on a news server). I track which user has read which article through a many-many relationship employing another table, Users_Articles, to do this.
The (cut down) schema is something like this:
Users:
user_id
user_name
Articles:
article_id
article_body
Users_Articles:
user_id
article_id
What I'm trying to do is SELECT a list of articles but to also display which article has already been read by the current user thus I'd like to add a boolean column to the set of columns in the SELECT statement which indicates if there is a row in Users_Articles which refers to the article for the current user.
you can go with left outer join
select
a.article_id, a.article_body,
ua.article_id as as been_read --will be not null for read articles
from Articles a
left outer join Users_Articles ua
on (ua.article_id = a.article_id and ua.user_id = $current_user_id)
or with subselect
select
a.article_id, a.article_body,
(select 1 from Users_Articles ua
where ua.article_id = a.article_id
and ua.user_id = $current_user_id) as been_read --will be not null for read articles
from Articles a