SQL Select Statement Duplicates

时间:2013-12-08 15:54:55

标签: mysql sql

我有三个SQL表(Movies,MovieCopy和RentalTransactions)。电影保存有关电影的数据,MovieCopy保存与特定DVD等的副本数量相关的数据,并用作电影和RentalTransactions之间的关联实体,RentalTransactions保存有关电影租赁的数据。

电影有10行数据(Movie1,Movie2,Movie3等,最多10行)。 MovieCopy有30行,这30行由Movies表中10个电影中的每一个的3个副本组成。 RentalTransactions有10行,与MovieCopy中的前10行相关。

我正在尝试运行一份报告,该报告将向我展示目前尚未借出的所有“DVD”类型的电影,因此这将是MovieCopy表格中剩余的20部电影。

下面是我试图提取此报告的SQL代码,但是当我执行此SQL时,我返回了290行,我不确定为什么会发生这种情况,理想情况下我希望只看到MovieCopy中的20行不属于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;

任何人都可以看到我的错误吗?

5 个答案:

答案 0 :(得分: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 );

答案 1 :(得分:0)

使用NOT EXISTS删除MovieCopy存在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

答案 2 :(得分:0)

您的表格结构错误。您使用RentalTransactions中的条目作为要租借的副本的标志。但是,当您执行查询时,这不会按预期工作。查询将查找电影类型为“DVD”并且在MovieCopy中具有相应条目的所有情况,但对于每个不属于自身的事务。这将产生重复。

此外,这会强制您在每次有人返回电影副本时删除条目,这会破坏任何形式的历史记录。

您需要拥有的是在MovieCopy中创建一个新属性,并根据是否租用该副本将其设置为true / false。

答案 3 :(得分:0)

这是一个有点复杂的查询。你的版本似乎有三个缺陷。第一种是不一致地使用表名,例如Transactions子句中的fromRentalTransactions作为别名。第二个是使用旧式连接。第三是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;

答案 4 :(得分: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)

对不起,根据您的问题创建了我自己的字段名称。 但是希望它可以帮到你,这会产生4行,电影表中的2行和电影拷贝表中的2行