mysql内部联接以关联所有元组

时间:2014-10-14 19:14:24

标签: mysql sql join data-retrieval

我有以下表格:

copy(movie_id,copy_id)
rented(copy_id,outdate,returndate)

如果租借电影,则在数据库中将returnsndate设置为null。

同一部电影会有多个副本。对于单个movie_id,我们可以有多个copy_id。

我需要检索已完全租借的电影,即电影的所有副本都已租出或以其他方式放置 - 电影的所有副本都出现在租借的表格中,并且返回设置为空。

我尝试了内部联接,但无法将副本表中的所有元组与租用的表相关联。

每个副本都有一个全局唯一的copy_id。因此,2个不同电影的副本不能具有相同的copy_id。

如果从未租借过该副本,它将不会显示在列表中,但这意味着该电影仍然有库存,因为它从未被租用过。这不应该出现。

如果多次租借,同一部电影和副本肯定会多次出租。

3 个答案:

答案 0 :(得分:1)

这比我想象的要困难一些。我相信这是正确的答案。

“所有电影的所有电影都存在租用的地方,其中返回者为空”

在数学符号中(A =全部,E =存在):

{m:M | (A c:C | c.movi​​e_id = m.movi​​e_id @(E r:R | r.copy_id = c.copy_id @ r.returndate = null))@ m.movi​​e_id}

可以改写为:

“所有不存在副本的电影,其中不存在租用的地方,其中返回为空”

转换为以下SQL。

SELECT DISTINCT m.movie_id
FROM Copy m
WHERE NOT EXISTS
  (SELECT 1 FROM Copy c
  WHERE c.movie_id = m.movie_id
  AND NOT EXISTS
    (SELECT 1 FROM Rented r
    WHERE r.copy_id = c.copy_id
    AND returndate IS NULL)

答案 1 :(得分:1)

您可以使用left join和聚合having子句来执行您想要的操作。然后,计算没有返回日期的记录数,并将其与副本数进行比较:

SELECT c.movie_id
FROM copy c LEFT JOIN
     rented r
     ON c.copy_id = r.copy_id
GROUP BY c.movie_id
HAVING SUM(r.returndate IS NULL) = COUNT(DISTINCT c.copy_id)

请注意使用SUM()进行比较。这会计算值为" true"。

的行数

以上查询假设一次不能多次租借一份副本。一个合理的假设,但总是值得检查。另一个having子句将此考虑在内:

HAVING count(distinct case when r.returndate is null then c.copy_id end) = count(distinct c.copy_id)

答案 2 :(得分:0)

您可以按movie_id进行分组,并计算returnsndate为null的位置:

SELECT DISTINCT movie_id
FROM copy
JOIN rented
ON copy.copy_id = rented.copy_id
GROUP BY copy.movie_id HAVING COUNT(rented.returndate IS NULL) = 0