How can we retrieve same data in one table? - sql

I need one very expert help, I can't seem to find the answer to this, the problem is, find the titles and ISBNs of books that have the same title and publishers as at least 2 other books.
Order it by title.
So basically, everything is coming from the book table.
CREATE TABLE BOOK
(
ISBN VARCHAR2(20),
Title VARCHAR2(250) NOT NULL,
YearPublished NUMBER(4) NOT NULL,
PublisherName VARCHAR2(40) NOT NULL,
CONSTRAINT pk_isbnP PRIMARY KEY(ISBN)
);
Here is my rough draft:
select _____
from book b2
where ______ (select____ from book b2
where _____ = ______ and ______ =______)

Step 1: Find combinations of title and publisher that have at least 2 books:
SELECT title, PublisherName
FROM BOOK
GROUP BY title, PublisherName
HAVING COUNT(*) > 1
Step 2: find all other books that have this title and publisher:
SELECT *
FROM Books b1
WHERE EXISTS(
SELECT title, PublisherName
FROM BOOK b2
WHERE b1.title = b2.title AND b1.PublisherName = b2.PublisherName
GROUP BY title, PublisherName
HAVING COUNT(*) > 1
)

This ought to do it:
select isbn, title
from books
where (title,publishername) in(select title,publishername
from books
group by title,publishername
having count(*) >=3)
order by title;

select b1.title, b1.isbn
from book b1
inner join
(select title, publishername
from book
group by title, publishername having count(*) > 2) b2
on b1.title = b2.title and b1.publishername = b2.publishername
order by b1.title
The inner query fetches the titles/publishers of books where there are three or more duplicates. The outer query uses those results to get the associated ISBNs.

You can use group by statement here.
SELECT title
,isbn
FROM BOOKS
group by title, isbn
having COUNT(1) >= 2 order by title;

Related

SQL Query Using Data from 2 tables

I have 2 tables: authors and books.
in authors i have attributes authorID, authorName, and authorDOB.
authorID is the primary key in this table.
in the books table i have attributes bookISBN, authorID, etc.
with bookISBN as the primary and authorID as the foreign key
i am trying to perform a query where given an author name, perform a
count of all the books by that author.
here is what i got:
SET #ID =
AuthorID
FROM authors
WHERE ('Mark Twain' = AuthorName);
SELECT COUNT(*)
FROM books
WHERE (AuthorID = ID);
Any help would be greatly appreciated
Try:
SELECT a.authorId, a.authorName, count(*)
FROM authors a
INNER JOIN books b ON b.AuthorID=a.AuthorID
WHERE ('Mark Twain' = a.AuthorName)
GROUP BY a.authorId, a.authorName
i am trying to perform a query where given an author name, perform a count of all the books by that author.
Try
select count(1)
from books b
inner join authors a on a.AuthorID=b.AuthorID
where a.AuthorName='Mark Twain'
You can use a function as well if you think you'd be doing the search more frequently. Just an idea.
go
create function totalbooksbyauthor (#authorname varchar(20) ) returns table
as return
select a.authorid, a.authorname, COUNT(b.bookname) bookcount
from authors a
inner join books b
on a.authorID = b.authorID
where a.authorname = #authorname
group by a.authorid, a.authorname
go
select * from totalbooksbyauthor ('Mark Twain')

Most efficient SQL for this example

Table A: Person: id, name
Table B: Toys: id, person_id, toy_name
I have a search screen that includes a dropdown of fixed toy names.
A search is found if a subset of the total set of toys for a person is matched.
Example, a person name=bob has toys: doll, car, house, hat
A search is done for person name=bob and toys=doll, hat.
I want to return bob and ALL of his toys, not just what toys were searched for(doll, hat).
Bob is found because a subset of his toys are a match.
I don't know what the most efficient/least db calls way to accomplish this.
I can do a search for bob and get all of his toys, then parse through the result set to see if the searched for toys find a match, but that seems wrong, that the db call could return rows for which no match is found (and that seems wrong?).
okay,
select
p.id,
p.name,
t.id as toyid,
t.toy_name
from
person p
join
toys t
on p.id = t.person_id
where
p.id in (
select person_id from toys where toy_name = 'doll'
intersect
select person_id from toys where toy_name = 'hat');
Fiddle Here
If you normalise your schema a little further,
create table Person
(
Id int,
Name varchar(100)
);
create table Toy
(
Id int,
Name varchar(100)
);
create table PersonToy
(
Id int,
PersonId int,
ToyId int
);
It should make the complexity of the problem clearer. It will also save some space. A statement of the form,
select
p.Name PersonName,
t.Name ToyName
from
Person p
join
PersonToy pt
on pt.PersonId = p.Id
join
Toy t
on t.Id = pt.ToyId
where
p.Id in
(
select PersonId from PersonToy where ToyId = 1
intersect
select PersonId from PersonToy where ToyId = 4
);
will work efficiently.
Updated Fiddle
Here's one way to do it using a subquery and checking for the existence of Hat and Doll in the HAVING clause:
select p.id, p.name,
t.id as toyid, t.name as toyname
from person p
inner join toys t on p.id = t.person_id
inner join (
select person_id
from toys
group by person_id
having sum(name = 'hat') > 0 and
sum(name = 'doll') > 0
) t2 on p.id = t2.person_id
SQL Fiddle Demo

SQL get count(x) from y where theres a specific x

How do I achieve a view in SQL for this? I want to get the number of books that exist in the shelf where book 2 is located. '2' is the book ID, and the book also has a shelf_id attributed to it. How do I find what shelf id it is and then search for how many books there are in it?
SELECT COUNT(b.book_id)
FROM book b, shelf s
I've tried a few things but am really not sure how to move forward.
SELECT COUNT(b2.*)
FROM book b1 JOIN book b2
ON b1.shelf_id = b2.shelf_id
where b1.book_id = 2;
or
SELECT COUNT(b2.*)
FROM book b2
where b2.shelf_id in (select shelf_id from book b1 where b1.book_id = 2);
If BOOK table already has shelf_id attribute, then the following query would return you the number of books in the same shelf as book 2:
SELECT COUNT(*) FROM books
WHERE shelf_id = (SELECT shelf_id FROM books WHERE book_id = 2)
This count include the book 2 as well, btw. The procedure definition for SQL Server would be as follows:
CREATE PROCEDURE sp_get_count_of_books_in_shelf_by_book_id
(
#book_id INT
)
AS
SELECT COUNT(*) FROM books
WHERE shelf_id = (SELECT shelf_id FROM books WHERE book_id = #book_id)
This should work fine:
SELECT COUNT(b.book_id)
FROM book b
INNER JOIN (SELECT s.shelf_id FROM book b1, shelf s WHERE b1.shelf_id = s.shelf_id AND b1.book_id = 2) j ON b.shelf_id = j.shelf_id

SQL Query - Need to get information from different table

I am trying to write a query to get a report that shows which book has been loaned out the most. I have a query to get the actual book loaned out most, but I need to be able to show the title of that book, which is in another table.
SELECT * FROM LOAN;
LOANID BOOKID CUSTID OUTDATE INDATE DUEDATE
SELECT * FROM BOOK;
AUTHORID BOOKID BKISBN BKSTATUS BKTITLE BKSERIES BKTYPE BKNUMBER
The following query is what I have so far and is getting the bookid.:
SELECT Q1.* FROM
(SELECT BOOKID, COUNT(*)
AS BOOK_COUNT
FROM LOAN
GROUP BY LOAN.BOOKID) Q1,
(SELECT MAX(Q2.BOOK_COUNT)
AS HIGH_COUNT
FROM (SELECT BOOKID, COUNT(*)
AS BOOK_COUNT
FROM LOAN
GROUP BY LOAN.BOOKID) Q2) Q3
WHERE Q1.BOOK_COUNT = Q3.HIGH_COUNT;
RESULT:
BOOKID BOOK_COUNT
---------- ----------
387 3
Now I need BkTitle from the Book Table.
Can anyone assist?
Try
select b.bookid, b.BKTITLE , count(l.loanid) as cnt_loan
from book b
inner join loan l on l.bookid = b.bookid
WHERE ROWNUM < 2
group by b.bookid
order by cnt_loan desc

SQL Query needed to get information from TWO separate tables

I am trying to create a query that will list all books by the same author. Most of the list has only one book by one author, but I want the author that has multiple books listed in db to display those book for that author.
I have two tables:
Book - AuthorID, BkTitle, etc
Author - AuthorID, AuthFName, AuthLName
I want the result to be sorted by AuthLName and the report to consist of any books in db that have same authorid.
Example result wanted:
AUTHORID BKTITLE AUTHFNAME AUTHLNAME
--------- ----------------- ------------ -----------
504 KNIGHT FREEDOM Chris Feehan
504 KNIGHT SHOWDOWN Chris Feehan
Currently, I have the following code:
select AUTHORID, BKTITLE
from BOOK
where AUTHORID in
(select AUTHORID from
(select AUTHORID,
count(*) as BOOK_COUNT
from BOOK
group by AUTHORid
order by AUTHORid )
where BOOK_COUNT >= 2);
which gives:
AUTHORID BKTITLE
---------- --------------------
504 KNIGHT FREEDOM
504 KNIGHT SHOWDOWN
I need to find a way to get the information from the Author Table and add it in this.
This should do:
SELECT b.AUTHORID, b.BKTITLE, a.AUTHFNAME, a.AUTHLNAME
FROM BOOK b
INNER JOIN AUTHOR a
ON b.AUTHORID = a.AUTHORID
AND b.AUTHORID IN
(
SELECT AUTHORID
FROM BOOK
GROUP BY AUTHORID
HAVING COUNT(AUTHORID) > 1
)
ORDER BY a.AUTHLNAME, a.AUTHFNAME
How about this - updated to use a CTE (Common Table Expression) first to figure out which authors have more than one book in the database table BOOK, and then listing only those authors and their books:
;WITH AuthorsWithMoreThanOneBook AS
(
SELECT AUTHORID, BOOK_COUNT = COUNT(*)
FROM BOOK
GROUP BY AUTHORID
HAVING BOOK_COUNT > 1)
)
SELECT
b.AUTHORID, b.BKTITLE, a.AuthFName, a.AuthLName
FROM
BOOK b
INNER JOIN
AUTHOR a ON b.AuthorID = a.AuthorID
INNER JOIN
AuthorsWithMoreThanOneBook A2 ON a.AuthorID = A2.AuthorID
ORDER BY
a.AuthLName, a.AuthFName
Update: OK, you're using Oracle .... not sure (haven't used it in ages) - but can't you just extend your original query something like this:
select bk.AUTHORID, bk.BKTITLE, a.AUTHORFNAME, a.AUTHORLNAME
from BOOK AS bk
INNER JOIN AUTHOR AS a ON a.AUTHORID = bk.AUTHORID
where bk.AUTHORID in
(select AUTHORID from
(select AUTHORID,
count(*) as BOOK_COUNT
from BOOK
group by AUTHORid
order by AUTHORid )
where BOOK_COUNT >= 2);
Not sure if/how Oracle supports those table aliases (BOOK AS bk) - but I'm pretty sure it does support it some way or another....
You can do this with only one access to each table:
SELECT * FROM
(
SELECT AuthorID, BkTitle, AuthFName, AuthLName
,COUNT(*) OVER (PARTITION BY AuthorID)
AS c
FROM BOOK
JOIN AUTHOR USING (AuthorID)
)
WHERE c > 1;