【问题标题】:How to group years in decades in sqlite3 in jupyter notebook?如何在 jupyter notebook 中的 sqlite3 中对几十年的年份进行分组?
【发布时间】: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`

标签: sql sqlite jupyter


【解决方案1】:

根据 cmets 中的要求对问题进行更新,以下几点可能有助于在不了解所有详细信息的情况下解决问题:

  • movie.year 列是否包含空值?同样是非数字或非日期值? NaN (Not A Number) 结果可能表示源中的数据为空/无效。 (从技术上讲,SQLite 中没有这样的 NaN 值,所以我假设问题数据是从其他数据网格或处理后的输出中复制的。)
  • movie.year 列中的数据类型是什么?它是否包含完整的 ISO-8601 日期字符串或儒略日期数值?或者它只包含年份(正如列名所暗示的那样)?如果它只包含年份(作为字符串或整数),那么像 strftime('%Y', year) 这样的函数调用将不会返回您所期望的并且是不必要的。直接参考专栏即可。
    • 我怀疑这就是 -461.0 的来源。
  • 如果两个操作数都是整数,则运算符/ 是一个“整数除法”运算符。一个有效的独立年份值将是一个整数,而文字 10 当然是一个整数,因此 整数除法将自动删除任何小数部分并仅返回除法的整数部分,而无需显式转换为整数。
  • 根据sqlite docs,串联运算符|| 具有最高优先级。这意味着在表达式decade||'-'||decade+9 中,首先应用连接,这样一个可能的中间值就是'1930-1930'+9。 (从技术上讲,我认为这个结果是未定义的,因为字符串值不包含基本数据类型。在我的系统上的实践中,字符串显然被解释为 1930,而整体结果是整数值 1939。无论哪种方式,你都会得到意想不到的假结果而不是所需的字符串。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-23
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 2018-09-17
    • 1970-01-01
    • 2020-08-23
    • 1970-01-01
    相关资源
    最近更新 更多