【发布时间】:2019-08-31 10:58:59
【问题描述】:
我假设找到电影数量和 D 中电影总数最多的十年 D。十年是连续 10 年的序列。例如,假设在您的数据库中,您有从 1965 年开始的电影信息。那么第一个十年是 1965、1966、...、1974;第二个是 1967、1968、...、1976 等等。
我想在我导入 sqlite3 的 jupyter 笔记本中实现这个 我为它写了如下代码。
Select count(*) as total_films,concat(decade,'-',decade+9)
FROM (Select floor(YEAR('year')/10)*10 as decade FROM movie) t
GROUP BY decade
Order BY total_films desc;
但是,笔记本抛出了“没有这样的功能:地板”和“没有这样的功能:年份”和没有这样的功能:concat”的错误
因此,在浏览完 sqlite 文档后,我将代码更改为
Select count(*) as total_films,decade||'-'||decade+9
FROM (Select cast(strftime('%Y',year)/10 as int)*10 as decade FROM movie) t
GROUP BY decade
Order BY total_films desc;
但是,我得到了一个不正确的输出:
count(*) decade||'-'||decade+9
0 117 NaN
1 3358 -461.0
希望能深入了解为什么会发生这种情况。
c.Perkins 通过 cmets 后更新问题
1) 我开始,检查年份列的类型
使用查询PRAGMA table_info(movie)
得到以下结果
cid name type notnull dflt_value pk
0 0 index INTEGER 0 None 0
1 1 MID TEXT 0 None 0
2 2 title TEXT 0 None 0
3 3 year TEXT 0 None 0
4 4 rating REAL 0 None 0
5 5 num_votes INTEGER 0 None 0
由于 year 列的类型为 text 我使用 cast 函数更改为 int 并检查 null 或 NaN SELECT CAST(year as int) as yr FROM MOVIE WHERE yr is null
我没有得到任何结果,因此似乎没有空值。但是,在使用查询SELECT CAST(year as int) as yr FROM MOVIE order by yr asc 时,我在年份列中看到很多零
yr
0 0
1 0
2 0
3 0
4 0
-
-
-
-
3445 2018
3446 2018
3447 2018
3448 2018
3449 2018
3450 2018
从上面我们看到,年份是按原样给出的,并且在另一个邮票中,因此使用 strftime('%Y', year) 没有产生评论中提到的结果。
因此,牢记以上所有内容,我将内部查询更改为
SELECT (CAST( (year/10) as int) *10) as decade FROM MOVIE WHERE decade!=0 order by decade asc
上述查询的输出:
decade
0 1930
1 1930
2 1930
3 1930
4 1930
5 1930
6 1940
7 1940
8 1940
-
-
-
3353 2010
3354 2010
3355 2010
3356 2010
3357 2010
最后,将这个内部查询放在我上面写的第一个查询中
Select count(*) as total_films,decade||'-'||decade+9 as period
FROM (SELECT (CAST( (year/10) as int) *10) as decade FROM MOVIE WHERE decade!=0 order by decade asc)
GROUP BY decade
输出:
total_films period
0 6 1939
1 12 1949
2 71 1959
3 145 1969
4 254 1979
5 342 1989
6 551 1999
7 959 2009
8 1018 2019
据我所知,唯一的问题是句号列,如果使用 ||是不对的,还有其他可以使用的功能吗?因为 concat 不工作。
提前致谢。
【问题讨论】:
-
您需要将信息缩减为必要的表和数据。关键问题主要是关于从单个列中获取数十年。此外,代码中唯一的源表是
movie。所有其他表模式都是不必要的,并且会分散这个问题的注意力。 更新问题以仅关注桌面电影。显示表movie中的示例行。 否则我们只能猜测数据的样子,因为您共享的最终数据是隐藏了详细信息的聚合数据。它有空值吗?year列是完整日期还是只有年份?等等。 -
此外,当外部查询结果不正确时,始终查看内部查询的结果是一种很好的调试习惯。它对于帮助您查看数据的人特别有用。包括裸列数据(在表达式之外),以便您可以确定表达式是否正确。换句话说,显示如下查询的结果:
SELECT year, cast(strftime('%Y',year)/10 as int)*10 AS decade FROM movie -
我已根据您的建议更新了问题,如果我错过了任何内容,请告诉我。提前致谢。
-
您对运算符和函数的作用做了太多假设,可能是因为它们在其他数据库或语言中的行为不同。例如,CAST(as Int) 不会为非字符串值返回 null,而是返回 0。如果要检查 null,则直接检查:
SELECT * FROM MOVIE WHERE year is null。如果需要,请使用WHERE Cast(year as int) = 0 AND year != '0'之类的内容检查其他非整数。 -
为什么要在 已经将列视为数字之后进行转换?对于表达式
CAST( (year/10) as int),sqlite 已经尝试将year强制转换为数值,以便将其除以10。如果它是数字,它已经完成了强制转换。如果它不是数字,它将返回 0,因此仍然不需要强制转换。尽管在这种情况下我没有看到结果有任何显着变化,但您需要注意操作的顺序以及它们是否有意义。如果你坚持强制转换,那么它应该是 'CAST(year as int) /10`