Select all items having silmutaneously 2different values at the same column - sql

I want to run an sql query and find all the books that have type="adventure" AND type="drama".
AND does not allow searching at the same time 2 different values of the same column.
My tables are like this
Books
Bid Bname Author
1 Sql loren
2 Monster Mike
3 Minnie Michel
----------
Copies
Cid Bid Type
1 1 Science
2 1 Teaching
3 2 Adventure
4 3 Romance
5 3 Drama
6 3 Adventure
The result I want:
Bid Title
3 Minnie
The tables can't change

There are several ways to do it, here is one using two exists conditions. Bottom line is that you have to check copies table twice.
SELECT * FROM books b
WHERE EXISTS
(
SELECT * FROM copies c1
WHERE b.bid = c1.bid
AND c1.type='adventure'
)
AND EXISTS
(
SELECT * FROM copies c2
WHERE b.bid = c2.bid
AND c2.type='drama'
)

You can achieve with JOIN, here is the DEMO. And you can use EXISTS as per #NenadZivkovic answer.
select
b.Bid,
Bname as Title
from books b
join Copies c
on b.Bid = c.Bid
and c.Type ='Drama'
join Copies c1
on c.Bid = c1.Bid
and c1.Type = 'Adventure'
group by
b.Bid,
Bname
order by
b.Bid

Related

Exclude Record using JOIN in SQL Server

I have 3 Tables,
Table MEmployee
ID Name
1 Andy
2 Donny
3 Mark
4 John
Table Basket
ID Name
1 Andy
Table Running
ID Name
2 Donny
And I want to create Soccer table from MEmployee Exclude Basket table and Running. The result like this
Table Soccer
ID Name
3 Mark
4 John
My Query doesn't work:
SELECT * FROM MEmployee A
INNER JOIN Basket B On A.ID = B.ID
INNER JOIN Running C ON A.ID = C.ID
WHERE A.ID <> B.ID AND A.ID = C.ID
We can try using EXCEPT here:
SELECT Name FROM MEmployee
EXCEPT
SELECT Name FROM Basket
EXCEPT
SELECT Name FROM Running;
Demo
You can use NOT EXISTS with CTE :
with t as (
select id, name
from Basket
union all
select id, name
from Running
)
select e.*
from MEmployee e
where not exists (select 1 from t where t.id = e.id);

SQL statement with pagination and sorting (join tables)

I have two tables (Books, Authors) with ManyToMany relationship. I need SQL statement to retrieve books with authors, sorted by authors/books. Important thing is that I must retrieve them with pagination (offset ... fetch in sql).
One of the problem that when I join tables there are duplicates in results (of course) and offset/fetch can't be used for this results. Another problem the results must be sorted (not subpages but all books of course).
I have one idea: (it retrieves books sorted by author name and include pagination)
select b.id, b.title, a.name from Books b inner join Books_Authors ba
on ba.bookID = b.id inner join Authors a
on ba.authorID = a.id
where a.name in (select name from Authors order by name offset 9 rows fetch next 3 rows only)
order by a.name
But I think it's not efficient way.
Something like this?
select * from
(
select tmp1.*, ROW_NUMBER() over(partition by b.title, a.name order by b.id, a.id) rang2
from
(
select a.id, b.id, b.title, a.name, ROW_NUMBER() over(partition by b.title, a.name order by b.id, a.id) rang
from Books b inner join Books_Authors ba on ba.bookID = b.id
inner join Authors a on ba.authorID = a.id
) tmp1 where rang=1
) tmp2
where rang2 between 3 and 9
order by title, name
table1
sno exam questions time_duration
1 unit test 1 10
2 mock 1 2 10
3 mock2 5 10
4 mock3 6 6
table2
qid answer user_attempt_option
1 1 1
2 2 3
2 3 4
3 4 1
3 1 2
3 2 3
3 3 1

Join one row only over three tables

(My question has been asked a lot of times with two tables involved, and has been answered here, here and here. But I can't figure out how to do the same with three tables involved.)
I have three tables, A, B and C, where A has many B and B has many C. I want to join these tables and select zero or one rows per A, which one should be based on a condition in C.
Example, assume that:
SELECT
a.aId
,b.bId
,c.cId
FROM
a
INNER JOIN b ON b.aId=a.aId
INNER JOIN c ON c.bId=b.bId
WHERE
c.someColumn='foo'
...yields the following result:
aId bId cId
=== === ===
1 11 101
1 12 102
1 12 103
2 21 201
2 21 203
2 22 202
...then I would like to, for instance, retrieve two distinct A-rows, the ones with highest cId.
aId bId cId
=== === ===
1 12 103
2 21 203
You can use ROW_NUMBER:
WITH Cte AS (
SELECT
a.aId,
b.bId,
c.cId,
rn = ROW_NUMBER() OVER (PARTITION BY a.aId ORDER BY c.cId DESC)
FROM a
INNER JOIN b
ON b.aId = a.aId
INNER JOIN c
ON c.bId = b.bId
WHERE c.someColumn = 'foo'
)
SELECT
aId, bId, cId
FROM Cte
WHERE rn = 1

SQL interview- how to get the record if there is no record or count is zero using multiple tables

I faced an interview and below is the question. The tables are below
Table1: Book (BookId is primary key)
BookId | Book_Title
1 | Book1
2 | Book2
3 | Book3
4 | Book4
5 | Book5
Table2: Book_Copies
BookId | BranchId | No_of_copies
1 1 2
1 2 5
2 1 0
2 2 2
2 3 0
3 1 0
3 2 0
The output should list all the Books with no stock at all as shown below.
Output:
Book_Title
---------
Book3
Book4
Book5
Please note that there are two possibilities. Either the 'No_of_copies' could be 0 or no record for a Book in the "Book_Copies" table.
For e.g.
the total number of copies for "Book3" is 0. The output should
include "Book3"
the total number of copies for "Book1 and "Book2" is 7 and 2
respectively. Both "Book1" and "Book2" shouldn't display
there is no entry for Book4 and Book5 in "Book_Copies", so both
should be included in output
After coming home, I wrote the below query after so many trials :)
select B.Book_Title
from
(
select BC.BookId, sum(BC.No_of_copies) as 'No of copies'
from Book_Copies BC
group by BC.BookId
having sum(BC.No_of_copies) = 0
union
select B.BookId, BC.No_of_copies
from Book B
left outer join Book_Copies BC on B.BookId = BC.BookId
where BC.BookId is null
)
as BookIds_withNoStock
inner join Book B on B.BookId = BookIds_withNoStock.BookId
This query works fine and tested properly.
Is there any way we can improve this query? like complexity, performance etc
If we can improve it, it would be helpful if you can provide the optimized query and reason. Thanks
You want books with no stock. I would approach this with a left outer join, aggregation, and a having clause:
select b.bookid, b.book_title
from book b left join
book_copies bc
on b.bookid = bc.bookid
group by b.bookid, b.book_title
having coalesce(sum(bc.no_of_copies), 0) = 0;
Try This
SELECT B.Book_Title
From Book B LEFT JOIN book_copies BC ON B.Bookid = BC.Bookid
Group By B.Book_Title
Having SUM(ISNULL(BC.no_of_copies,0)) = 0
FIddle Demo
Output:
BOOK_TITLE
Book3
Book4
Book5
The below code worked for me:
SELECT a.Book_Title
FROM #books a
left join(
SELECT BookId,sum(No_of_copies) Cnt
FROM #Book_Copies
GROUP BY BookId) b
ON a.BookId = b.BookId
WHERE b.cnt = 0 OR b.Cnt is null
try this:
select Book_Title from Book left join Book_Copies on Book.BookId = Book_Copies.BookId
group by Book_Title having
SUM(Book_Copies.No_of_copies) IS NULL OR SUM(Book_Copies.No_of_copies)=0
select book_title
from books
where book_id NOT IN
(
select book_id
from book_copies
group by book_id
having sum( no_copies) > 0
)

sql query for 3 tables

i have 3 tables (A,B,C)
Table A -
ID Name
1 Sam
2 Manuel
3 Jane
Table B
ID Tab_A_ID Name
1 1 Meer
2 1 Kutti
3 2 Mikaro
Table C
ID Tab_B_ID Price
1 1 255.11
2 1 30.52
3 3 125.22
I need a query that shall pick up the top price for TableA-Name from TableC. So only 1 top price for 1 nae record.
e.g.-
Sam - 255.11
Manuel - 125.22
How can i get this?
To get the max price per entry in A:
SELECT a.Name,
MAX(c.price)
FROM a
INNER JOIN b
ON a.id = b.tab_a_id
INNER JOIN c
ON b.id = c.tab_b_id
GROUP BY a.id, a.name
To get the max price per entry A per entry B:
SELECT a.Name,
b.Name
MAX(c.price)
FROM a
INNER JOIN b
ON a.id = b.tab_a_id
INNER JOIN c
ON b.id = c.tab_b_id
GROUP BY a.id, b.id, a.name, b.name
Note that entries in A without corresponding entires in B or entries in B without corresponding entries in C will not appear in the result. Use LEFT JOIN if you want to include these in the result.