作为一名SQL外行,我从Stanford的SQL课程进行一些数据修改查询以进行练习。尽管我设法使用IN运算符完成了最后一个练习,但对我来说还是有些棘手。作为一个小插件,我尝试为子查询使用EXISTS重写查询。事实证明,这比预期的要难,所以现在我想知道是否会有更优雅的方法。
大约是在第四季度:“删除电影年份在1970年之前或2000年之后且评分少于4星的所有评分。”
SQL小提琴可以在这里找到:http://www.sqlfiddle.com/#!9/f7f3ad
非常感谢您!
我首先尝试将附加的AND语句拖到子查询中,仅将IN替换为EXISTS。在我发现这实际上将删除整个表之后不久,因为Exists-clause会在不引用外部表的情况下评估为true。
意识到这一点,我尝试在外部表中使用Alias,以便能够从内部明确引用外部表。但是,系统不允许我这样做。我相信他们正在运行Postgres,而我们正在Uni上使用MySQL。您知道MySQL是否允许在数据修改语句中使用别名吗?
现在查询本身。在我看来,它很冗长。是否存在使用EXISTS进行此操作的更明智的方法?或者也许完全不依赖IN /存在的东西完全不同。
使用IN:
Delete
FROM Rating
Where MId IN
(
/*movies either before 1970 or after 2000*/
Select r.MId
FROM Movie as m
INNER JOIN Rating as r
on m.MId = r.MId
WHERE m.year <1970 Or m.year > 2000
)
-- pick those with less than 4 stars
AND stars < 4;
使用存在的内容
Delete
FROM Rating
Where EXISTS(
Select *
FROM Movie as m
INNER JOIN Rating as r
on m.MId = r.MId
WHERE (m.year <1970 Or m.year > 2000) AND r.stars < 4
AND Rating.rId = r.RId AND Rating.Mid = r.MId AND Rating.stars <4
);
让我苦苦挣扎的一件事是检查外部表中的星星是否小于4的最后一点。对我来说,我似乎在联接条件内完成整个查询的工作。但是,我发现不进行此操作实际上会删除rId 201的所有评分,因为它发现符合条件的前201个元组(超出日期范围,少于4星),并得出结论,既然存在,它也可以删除另一个元组(其中的星星实际上> = 4)
答案 0 :(得分:1)
在这样的语句中,MySQL不允许您引用正在更新或删除的表。就您而言,这很容易解决。
我更喜欢exists
:
delete r from rating r
where exists (select 1
from Movie m
where m.MId = r.MId and
(m.year < 1970 or m.year > 2000)
) and
-- pick those with less than 4 stars
r.stars < 4;
您可以使用in
做类似的事情:
delete r from rating r
where r.MId in (select m.MId
from Movie m
where m.year < 1970 or m.year > 2000
) and
-- pick those with less than 4 stars
r.stars < 4;
答案 1 :(得分:0)
使用JOIN
DELETE r FROM Rating r
INNER JOIN Movie m ON r.mID=m.mID
WHERE r.stars<4 AND (m.year<1970 OR m.year>2000);