oracle: aliasing problem, why isn't recognizing it? - sql

Ok guys, im having a real issue trying to understand the logic behind the aliasing in oracle. Here is the query:
select isbn,
b.fname,
b.lname
from bookauthor a,
author b,
(select authorid auth
from bookauthor
where isbn = (select max(isbn) maxisbn
from orderitems))
where b.authorid = auth
and isbn = maxisbn;
for some reason, the dbms isn't recognizing maxisbn as an alias, but if i get rid of everything regarding maxisbn, the query runs and recognizes the alias "auth" just fine. Why is it seeing one but not the other?

maxisbn isn't the name of any column exposed by your derived table's SELECT list.
In order for this syntax to work you would need to add it as a column as below.
select isbn,
b.fname,
b.lname
from bookauthor a,
author b,
(select authorid auth, isbn maxisbn
from bookauthor
where isbn = (select max(isbn) maxisbn
from orderitems))
where b.authorid = auth
and isbn = maxisbn;
NB: There is probably definitely a more efficient way of writing this query (you shouldn't need to access bookauthor twice) and I would always use explicit JOIN syntax. This is just to answer your specific question about why it doesn't work.

To take up Martin's question if this can be written more efficiently.
I think that the following will perform better and still return the same thing:
SELECT a.max_isbn,
b.fname,
b.lname
FROM (SELECT authorid as max_authorid,
isbn as max_isbn
FROM bookauthor
WHERE isbn = (SELECT max(isbn) FROM orderitems)) a
JOIN author b ON a.max_authorid = b.authorid AND a.max_isbn = b.isbn

Related

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

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.

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

SQL: Querying Against Composite Entity

I'm trying to figure out how to query against a composite key.
In my select result, I want the book name, author, category, and selling price. So far I have select title,category,price from books1 where books1.category='MYS';
but I'm not sure how to go about getting the author name.
I'm not sure why you have books1 when the model show the table named books. Books is a horrible name for a table -- typically in relational databases you use the singular -- eg book.
Here is how you do a join:
Select a.First, a.Last
from books b
join books_authors ab on b.b_code = ab.book_code
join authors a on ab.authorId = a.id
where b.category = 'MYS'
also all of your field names have spaces in them -- I don't know what platform you are using so I've no idea how to escape the names. Using spaces in field name is non-standard and not acually SQL. I'd advise against it whenever possible.

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

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 :-)