Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sqlite 查找电影在发行当年的出租次数_Sqlite - Fatal编程技术网

Sqlite 查找电影在发行当年的出租次数

Sqlite 查找电影在发行当年的出租次数,sqlite,Sqlite,我有这样的设置: Movies ( movieId INTEGER PRIMARY KEY, title TEXT, year INTEGER ) Rentals ( cardNo INTEGER, movieId INTEGER, date DATE, rating INTEGER, PRIMARY KEY(cardNo, movieID, date), FOREIGN KEY (cardNo) REFERENCES C

我有这样的设置:

Movies (
    movieId INTEGER PRIMARY KEY,
    title TEXT,
    year INTEGER
)

Rentals (
    cardNo INTEGER,
    movieId INTEGER,
    date DATE,
    rating INTEGER,
    PRIMARY KEY(cardNo, movieID, date),
    FOREIGN KEY (cardNo) REFERENCES Customers,
    FOREIGN KEY (movieId) REFERENCES Movies
)
我想知道哪部电影在一年中被出租的次数最多,如果且仅当电影在那一年发行

例如:如果电影_x在2003年租得最多,但在2003年也没有发行,那么它就不算了。如果这部电影都是在2003年发行的,并且在2003年租了最多的(当年发行的电影),那么它确实算数

我想我需要设置一个临时表来存储
movieId
count(movieId)
,这样我就可以对计数执行select
max()


我正在使用python,因此我可以将
max()
movieId
存储在一个变量中,然后检查原始
movies
列以将其与电影的标题匹配,如果有帮助的话。

这个答案中使用的策略是将
租赁
电影
表连接在一起,以匹配
电影ID
和年份。这用于丢弃
租赁
表中未在电影发行的同一年出现的任何记录

我们可以聚合这样一个连接,然后生成整个数据库的年/电影租赁计数。但是,由于您只希望电影在给定的一年中拥有最高的出租率,我们需要做更多的工作。在本例中,我们可以找到每年最高的租金计数(请参见下面的子查询
t2
),并加入前面描述的子查询

SELECT
    t1.movieId,
    t1.title,
    t1.year,
    t1.num_rentals
FROM
(
    SELECT
        m.movieId,
        m.title,
        m.year,
        COUNT(*) AS num_rentals
    FROM Rentals r
    INNER JOIN Movies m
        ON r.movieId = m.movieId AND CAST(SUBSTR(r.date, 1, 4) AS INTEGER) = m.year
    GROUP BY
        m.movieId,
        m.title,
        m.year
) t1
INNER JOIN
(
    SELECT year, MAX(num_rentals) AS max_num_rentals
    FROM
    (
        SELECT
            m.year,
            COUNT(*) AS num_rentals
        FROM Rentals r
        INNER JOIN Movies m
            ON r.movieId = m.movieId AND CAST(SUBSTR(r.date, 1, 4) AS INTEGER) = m.year
        GROUP BY
            m.movieId,
            m.year
    ) t
    GROUP BY year
) t2
    ON t1.year = t2.year AND t1.num_rentals = t2.max_num_rentals
-- WHERE t1.year = 2003
ORDER BY
    t1.year;

这个答案将报告所有年份,以及该年发行的所有租金最高的电影。如果某一年中有两部或两部以上的电影出现平局,则会报告所有平局的电影


请注意,如果SQLite支持分析函数,查询可以大大简化。

这里有一种稍微不同的方法,使用CTE而不是嵌套子查询

WITH first_year_rentals(movieid, title, rentals, year) AS
      (SELECT m.movieid, m.title, count(*), m.year 
       FROM movies AS m 
       JOIN rentals AS r ON m.movieid = r.movieid AND m.year = strftime('%Y', r.date)
       GROUP BY m.movieid)
    , maximums(year, maxrent) AS
      (SELECT year, max(rentals)
       FROM first_year_rentals
       GROUP BY year)
SELECT movieid, title, rentals, f.year AS year
FROM first_year_rentals AS f
JOIN maximums AS m ON f.year = m.year AND m.maxrent = f.rentals 
ORDER BY f.year, title;
CTE(公共表表达式)类似于只存在一条语句的视图。非常方便地组织具有多个查询的语句。第一个生成的结果计算出每部电影在发行当年的出租次数。第二个是每年新版本的最高租金。然后,只需加入两个CTE,并将结果限制在租赁数量等于该电影发行年度最高的行

编辑:

使用以下表格和数据进行测试:

CREATE TABLE Movies (
    movieId INTEGER PRIMARY KEY,
    title TEXT,
    year INTEGER
);
INSERT INTO Movies VALUES(1,'a good movie',2003);
INSERT INTO Movies VALUES(2,'a better movie',2003);
INSERT INTO Movies VALUES(3,'the best movie',2004);
INSERT INTO Movies VALUES(4,'the worst movie',2004);
CREATE TABLE Rentals (
    cardNo INTEGER,
    movieId INTEGER,
    date DATE,
    rating INTEGER,
    PRIMARY KEY(cardNo, movieID, date),
    -- FOREIGN KEY (cardNo) REFERENCES Customers,
    FOREIGN KEY (movieId) REFERENCES Movies
);
INSERT INTO Rentals VALUES(1,1,'2003-01-01',NULL);
INSERT INTO Rentals VALUES(1,2,'2003-01-01',NULL);
INSERT INTO Rentals VALUES(1,3,'2006-01-01',NULL);
INSERT INTO Rentals VALUES(2,1,'2003-01-01',NULL);
INSERT INTO Rentals VALUES(2,3,'2004-01-01',NULL);
INSERT INTO Rentals VALUES(2,2,'2004-01-01',NULL);
INSERT INTO Rentals VALUES(3,2,'2003-01-01',NULL);
INSERT INTO Rentals VALUES(3,1,'2005-01-01',NULL);
INSERT INTO Rentals VALUES(3,4,'2004-01-01',NULL);
INSERT INTO Rentals VALUES(4,2,'2003-01-01',NULL);
INSERT INTO Rentals VALUES(4,4,'2004-01-01',NULL);
INSERT INTO Rentals VALUES(5,1,'2003-01-01',NULL);
给予:

movieid     title           rentals     year      
----------  --------------  ----------  ----------
2           a better movie  3           2003      
1           a good movie    3           2003      
4           the worst movi  2           2004 

进一步编辑:

在另一个答案中提到分析函数提醒了我;sqlite现在有了它们(添加在3.25中)!所以

它使用窗口函数将第一个查询中的两个CTE合并为一个CTE。(可能还有更好的方法;我还不能非常流利地使用它们)

以及使用排名建议的不同版本:

WITH first_year_rentals(movieid, title, rentals, ranking, year) AS
     (SELECT m.movieid
           , m.title
           , count(*)
           , rank() OVER (PARTITION BY m.year ORDER BY count(*) DESC)
           , m.year
      FROM movies AS m 
      JOIN rentals AS r ON m.movieid = r.movieid AND m.year = strftime('%Y', r.date)
      GROUP BY m.movieid)
SELECT movieid, title, rentals, year
FROM first_year_rentals 
WHERE ranking = 1
ORDER BY year, title;

一次只能报告一年,或者您的报告有几年?它可以包含几年。我认为我最头疼的事情是创建一个临时表,其中包含电影id列和租用次数列,只要电影在给定的年份发行并在给定的年份租用。如果我能弄清楚如何做到这一点,那么我可以在它的#of times rendered列上运行max()查询,找到电影id,然后链接到电影标题。我尝试了下面的答案。一些样本数据可能会有帮助。如果是领带,你想要什么?@Shawn所有领带的电影都应该包括在内。我真正想要的是创建一个临时表的方法,其中包括电影id和电影在给定年份的出租次数,只要电影在给定年份发布。我可以很容易地解决这个问题。我不确定我是否能够理解这里发生的事情,因为我对SQL非常陌生。有没有办法只创建一个临时表,其中在一列中包含电影id和电影出租次数,并且只有在电影的出租和发行日期发生在给定年份时才有电影条目?我也在db上运行了这个,它似乎不能正常工作。它返回了错误的电影。@Mdomin45我想我们可以让上面的查询为您服务。请尝试一下并留下反馈,谢谢。在给定的一年中,我会把它放在哪里?假设我想检查2000年。给定年份的硬编码会改变整个查询,既然你没有要求,我不愿意改变我的整个答案。一个快速的方法是在外部查询中添加一个
WHERE
子句,查看我的更新答案。它仍然给出了不正确的答案。我希望我能解释一下原因,但我使用的数据库相当大,我对代码本身了解甚少。@TimBiegeleisen更新。我怀疑您的fiddle不起作用,因为您没有使用与年份列具有适当关联的实际表,这意味着
strftime()
返回的字符串没有转换为数字,因此比较失败。当Sqlite在比较中转换值时,它有时会很棘手而且不明显。是的,它现在看起来很好+1。不幸的是,我的大脑太油腻了,无法理解你的查询,但它似乎起作用了。@TimBiegeleisen我用窗口函数抛出了第二个版本,它也油腻了我的大脑。这些东西都是黑魔法。好的……另一种方法是使用
RANK
densite\u RANK
,在年份上划分分区,在计数下降时使用
ORDER BY
。然后,只保留rank=1记录(这将捕获第一名的所有关系)。
WITH first_year_rentals(movieid, title, rentals, ranking, year) AS
     (SELECT m.movieid
           , m.title
           , count(*)
           , rank() OVER (PARTITION BY m.year ORDER BY count(*) DESC)
           , m.year
      FROM movies AS m 
      JOIN rentals AS r ON m.movieid = r.movieid AND m.year = strftime('%Y', r.date)
      GROUP BY m.movieid)
SELECT movieid, title, rentals, year
FROM first_year_rentals 
WHERE ranking = 1
ORDER BY year, title;