2013-12-08 88 views
0

我有三個SQL表(Movies,MovieCopy和RentalTransactions)。電影保存有關電影的數據,MovieCopy保存與特定DVD的副本數量有關的數據,並且用作電影和RentalTransactions之間的關聯實體,RentalTransactions保存關於電影租賃的數據。SQL Select Statement Duplicates

電影有10行數據(電影1,電影2,電影3等10)。 MovieCopy有30行,這30行由Movies表中10個電影中的每一個的3個副本組成。 RentalTransactions有10行,與MovieCopy中的前10行相關。

我試圖運行一個報告,它會顯示所有類型爲'DVD'的電影,這些電影目前還沒有借出,因此這將是MovieCopy表中剩餘的20部電影副本。

下面是我的SQL代碼試圖拉這個報告,但是當我執行這個SQL時,我返回290行,我不知道爲什麼這是完全發生,理想情況下,我想看到只有20行MovieCopy這些不在RentalTransactions中。

Select Movies.Movie_Name, Movies.Movie_Type, 
    Movies.Movie_Medium, Count(MovieCopy.Movie_CopyID) as Copies 
FROM Movies,MovieCopy,RentalTransactions 
WHERE Movies.Movie_Medium = 'DVD' and Movies.MovieID = MovieCopy.MovieID 
    and MovieCopy.Movie_CopyID <> RentalTransactions.Movie_CopyID; 

任何人都可以看到我的錯誤嗎?

回答

0
Select Movies.Movie_Name, Movies.Movie_Type, 
    Movies.Movie_Medium, Count(MovieCopy.Movie_CopyID) as Copies 
FROM Movies,MovieCopy,RentalTransactions 
WHERE Movies.Movie_Medium = 'DVD' and Movies.MovieID = MovieCopy.MovieID 
    and MovieCopy.Movie_CopyID NOT IN (SELECT Movie_CopyID FROM RentalTransactions); 
0

使用NOT EXISTSMovieCopy其中RentalTransactions存在,GROUP BY刪除所有行獲取每部電影的計數器。

Select 
    Movies.Movie_Name, Movies.Movie_Type, Movies.Movie_Medium, 
    Count(1) as Copies 
FROM Movies 
JOIN MovieCopy ON (MovieCopy.MovieId = Movies.MovieId) 
WHERE Movies.Movie_Medium = 'DVD' 
NOT EXISTS 
(
    SELECT 1 
    FROM RentalTransactions 
    WHERE RentalTransactions.Movie_CopyID = MovieCopy.Movie_CopyID 
) 
GROUP BY 
    Movies.Movie_Name, Movies.Movie_Type, Movies.Movie_Medium 
0

您的表結構錯誤。您正在使用RentalTransactions中的條目作爲正在租用或未租用副本的標誌。但是,當您執行您的查詢時,這不符合您的預期。該查詢將查找所有電影類型爲「DVD」的情況,並且在MovieCopy中具有相應的條目,但對於不是其本身的每個事務。這將創建重複。

此外,這將迫使你刪除條目,每次有人返回電影副本,這將破壞任何形式的歷史。

您需要的是在MovieCopy中創建一個新屬性,並根據副本是否被租用將其設置爲true/false。

+0

我將如何去設置它爲true/false取決於它是否出租或不? 我猜只知道它是否被租用的唯一方法是如果在RentalTransactions中存在MovieCopy_ID? – Eoin090

+0

當事件發生時,您可以使用UPDATE查詢修改正確MovieCopy的標誌並將其設置爲true/false。您將需要更改表以添加新列。正如我所說,技術上你在做什麼*可以*工作,但它有主要的缺點。值得注意的是,你將不得不刪除以前的租金,以再次租用該電影的副本。這使得不可能保持歷史。您必須首先在單獨的「TransactionHistory」表中創建數據副本,然後刪除前一個表中的數據。 – ApplePie

0

這是一個有點複雜的查詢。你的版本似乎有三個缺陷。首先是表名稱的不一致使用,如from子句中的TransactionsRentalTransactions作爲別名。第二種是使用舊式聯接。三是不一致的使用group by

因爲制定查詢的一種方法是使用left outer join,舊式隱式聯接是一個真正的問題。

邏輯是根據介質過濾電影。然後,將外部加入租賃表並僅選擇沒有租賃記錄的副本。

Select m.Movie_Name, m.Movie_Type, 
     m.Movie_Medium, Count(MovieCopy.Movie_CopyID) as Copies 
FROM Movies m join 
    MovieCopyRental mcr 
    on m.MovieID = mc.MovieID and m.Movie_Medium = 'DVD' left outer join 
    RentalTransactions rt 
    on mcr.Movie_CopyID = rt.Movie_CopyID and   
WHERE rt.Movie_CopyId is NULL 
GROUP BY m.Movie_Name, m.Movie_Type, m.Movie_Medium; 

如果你希望所有的電影,包括那些沒有副本的列表,然後將where條款更改爲有條件聚集:

Select m.Movie_Name, m.Movie_Type, m.Movie_Medium, 
     count(*) as TotalCopies, sum(rt.Movie_CopyId is NULL) as RemainingCopies 
FROM Movies m join 
    MovieCopyRental mcr 
    on m.MovieID = mc.MovieID and m.Movie_Medium = 'DVD' left outer join 
    RentalTransactions rt 
    on mcr.Movie_CopyID = rt.Movie_CopyID and   
GROUP BY m.Movie_Name, m.Movie_Type, m.Movie_Medium; 
0

你能做到這一點

select mov.movie_id , mov.movietitle , cpm.movie_id , cpm.movietitle from tbl_movies as mov 
left join tbl_moviescopy as cpm on cpm.movie_id = mov.movie_id 
where movie_type = 'DVD' 
and movie_id not exists (select movie_id from rentaltransactions) 

IM對不起,根據你的問題創建了我自己的字段名稱。 但希望它可以幫助你,這將產生4行,2從電影表和2從電影複製表