范围内每个数字的 SQL 计数总计(编辑:通过 UDF)

Posted

技术标签:

【中文标题】范围内每个数字的 SQL 计数总计(编辑:通过 UDF)【英文标题】:SQL count totals for each number in a range (Edit: via a UDF) 【发布时间】:2015-07-25 05:37:05 【问题描述】:

我在 Amazon (AWS) RedShift 中有类似以下的数据,它代表了不同人的阅读日志,每一行都是特定日期阅读的章节跨度的记录:

| person | date   | book     | chapter_start | chapter_end |
|--------|--------|----------|---------------|-------------|
| Alice  | 7/1/15 | Big Red  | 4             | 7           |
| Bob    | 7/1/15 | Big Red  | 1             | 5           |
| James  | 7/1/15 | Big Red  | 2             | 9           |
| Tim    | 7/1/15 | Big Red  | 10            | 12          |
| Alice  | 7/2/15 | Big Red  | 8             | 10          |
| Bob    | 7/2/15 | Big Red  | 6             | 8           |
| James  | 7/2/15 | Big Red  | 10            | 11          |
| Tim    | 7/1/15 | Blue Sky | 1             | 3           |
| Alice  | 7/1/15 | Blue Sky | 3             | 4           | 

我想知道是否有一个 SQL 查询(记住它需要与 RedShift 兼容的 postgresql)可以为跨度中的每一章产生一个计数,以便结果如下所示:

| book     | chapter | count |
|----------|---------|-------|
| Big Red  | 1       | 1     |
| Big Red  | 2       | 2     |
| Big Red  | 3       | 2     |
| Big Red  | 4       | 3     |
| Big Red  | 5       | 3     |
| Big Red  | 6       | 3     |
| Big Red  | 7       | 3     |
| Big Red  | 8       | 3     |
| Big Red  | 9       | 2     |
| Big Red  | 10      | 3     |
| Big Red  | 11      | 2     |
| Big Red  | 12      | 1     |
| Blue Sky | 1       | 1     |
| Blue Sky | 2       | 1     |
| Blue Sky | 3       | 2     |
| Blue Sky | 4       | 2     |

请注意,在上面的结果中,计数不仅仅考虑了 chapter_start 和 chapter_end。例如,如果我们处理 Tim 从第 1 章到第 3 章读取 Blue Sky 的条目,则 Blue Sky 的第 1、2 和 3 章应该增加各自的计数器。

编辑(2015 年 7 月 28 日):经过进一步研究,似乎 Mureinik 的以下建议适用于完全符合 postgresql 的系统,但 RedShift 仅支持一小部分 postgresql 函数(请参阅: Unsupported PostgeSQL Functions in RedShift) 因此他的回答不适用于 RedShift。目前,这似乎也无法通过用户定义函数 (UDF) 实现,因为它们也不支持。令人鼓舞的一点是,RedShift 产品经理确认他们计划在 2015 年 9 月之前支持符合 postgresql 的 UDF。>

如上所述,是否有人愿意通过 UDF 承担相当于 GENERATE_SERIES() 的任务?

编辑(2015 年 9 月 11 日): UDF 终于在 RedShift 中可用。请参阅新发布的AWS RedShift UDF documentation。澄清需求——需要的是 python 中的一个集合返回函数,它复制了Postgres GENERATE_SERIES() function 的功能。有人愿意挑战吗?

编辑(2016 年 1 月 8 日):在与 AWS 反复讨论并对其文档进行一些澄清后,RedShift 中支持的 UDF 似乎只能返回单个值,而不是一组.因此,目前似乎不可能创建一个模仿此功能的 UDF。

【问题讨论】:

【参考方案1】:

您可以使用generate_series 创建chapter_startchapter_end 之间所有章节的列表,然后按它们分组并计数:

SELECT   book, chapter, COUNT(*)
FROM     (SELECT book, GENERATE_SERIES(chapter_start, chapter_end) AS chapter
          FROM   mytable) t
GROUP BY book, chapter

【讨论】:

Mureinik,您的解决方案在 postresql 中运行良好,但在 RedShift 集群上执行时失败,并出现错误:“Redshift 表不支持指定的类型或函数(每个 INFO 消息一个)”。这很令人失望,因为 SELECT * FROM generate_series(2,4); 的简单测试它确实在我的 RedShift 集群上正确执行。结果 GENERATE_SERIES() 在 RedShift (docs.aws.amazon.com/redshift/latest/dg/…) 的不支持函数列表中。还有其他建议吗?

以上是关于范围内每个数字的 SQL 计数总计(编辑:通过 UDF)的主要内容,如果未能解决你的问题,请参考以下文章

SQL 使用 group_concat 与每个连接项目的计数,而不是在一行中的总计数

在线性时间内对 0 到 n^2 – 1 范围内的 n 个数字进行排序

计算 SQL 中日期字段的计数和运行总计

如何使用 sql 中的单个查询获取项目计数和总计数?

如何通过 PL-Sql 获取数字范围内的数字。?

sql 互联网销售计数的运行总计