Reputation: 2016
I have two tables for my system.
Table 1: Book
Table 2: BookStatus
Now I want to find out the latest status of books that had been lent from 2018/11/05 to 201/11/10 and how many times they have been lent during this period.
The result I expect is like:
My SQL script is:
SELECT BK.*,
BS.status, BS.statusDateTime,
(SELECT count(*) FROM BookStatus WHERE status='lent' AND bookId=BK.bookId AND statusDateTime>='2018/11/05 00:00:00' AND statusDatetime<='2018/11/10 23:59:59' ) CountLent
FROM Book BK LEFT JOIN BookStatus BS ON BK.bookId = BS.bookId
WHERE BS.statusId = (SELECT max(statusId) FROM BookStatus WHERE bookId= BK.bookId)
AND BK.bookId IN (SELECT bookId FROM BookStatus WHERE status='lent' AND statusDateTime>='2018/11/05 00:00:00' AND statusDatetime<='2018/11/10 23:59:59')
After I execute the sql query, it just keeps running and doesn't stop. Is there any problem with my SQL query script? How to revise my SQL script to have the result I expect?
Upvotes: 1
Views: 142
Reputation: 11
I tried run your code, and it was ok, but result was not true! You can try this:
SELECT bd.bookID, bk.bookName, bk.author,
statusID, status, statusDateTime ,bc.countLent
FROM ( SELECT bookID, statusDate = MAX(statusDateTime)
FROM bookStatus
GROUP BY bookID
) AS bd
LEFT JOIN ( SELECT bookID, COUNT(*) AS countLent
FROM bookStatus
WHERE [status] = 'lent'
GROUP BY bookID
) AS bc ON bc.bookID = bd.bookID
LEFT JOIN dbo.bookStatus ON bookStatus.bookID = bc.bookID
AND bd.statusDate = dbo.bookStatus.statusDateTime
LEFT JOIN Book AS bk ON bk.bookID = bookStatus.bookID
The result is good but I know my code is not the best way :D Hope this's help
Upvotes: 0
Reputation: 272096
Find out all the books that were lent during the period and the count using a sub query. Use CROSS APPLY
to fetch the latest status:
WITH activity AS (
SELECT bookId, COUNT(*) AS CountLent
FROM BookStatus
WHERE statusDateTime >= '2018-11-05' AND statusDateTime < DATEADD(DAY, 1, '2018-11-10')
AND status = 'lent'
GROUP BY bookId
)
SELECT Book.*, activity.CountLent, lastStatus.*
FROM Book
INNER JOIN activity ON Book.bookId = activity.bookId
CROSS APPLY (SELECT TOP 1 status, statusDateTime FROM BookStatus WHERE bookId = Book.bookId ORDER BY statusDateTime DESC) AS lastStatus
Upvotes: 1
Reputation: 119
Please try your query like below-
select b.bookid ,b.bookName , b.Author
,bs.status ,max(bs.statusDatetime), count(bs.status) Countlent
from Book b
join BookStatus bs on b.bookid= bs.bookid
where bs.statusDateTime >='2018/11/05 00:00:00' AND bs.statusDatetime<='2018/11/10 23:59:59'
and bs.status = 'lent'
group by b.bookid ,b.bookName , b.Author ,bs.status
Hope this will help you.
Upvotes: 2
Reputation: 37473
You can try below
select b.bookid ,b.bookName , b.Author ,bs.status ,
max(bs.statusDatetime) as statusDatetime, count(bs.status) Countlent
from Book b
join BookStatus bs on b.bookid= bs.bookid
where bs.statusDateTime >='2018/11/05 00:00:00' AND bs.statusDatetime<='2018/11/10 23:59:59' and bs.status = 'lent'
group by b.bookid ,b.bookName , b.Author ,bs.status
Upvotes: 0