每日查询计数,并具有多周的日期限制

2023-12-14

我正在尝试每天查找 # 个活跃用户。

用户在创建后即处于活动状态多于每周 10 个请求,共 4 个连续几周.

IE。 2014 年 10 月 31 日,如果用户在以下时间段内每周发出的请求总数超过 10 个,则该用户处于活动状态:

  1. 2014年10月24日至10月30日AND
  2. 2014年10月17日-10月23日AND
  3. 2014年10月10日-10月16日AND
  4. 2014年10月3日-10月9日

我有一张桌子requests:

CREATE TABLE requests (
  id text PRIMARY KEY, -- id of the request
  amount bigint,       -- sum of requests made by accounts_id to recipient_id,
                       -- aggregated on a daily basis based on "date"
  accounts_id text,    -- id of the user
  recipient_id text,   -- id of the recipient
  date timestamp       -- date that the request was made in YYYY-MM-DD
);

样本值:

INSERT INTO requests2
VALUES
    ('1',  19, 'a1', 'b1', '2014-10-05 00:00:00'),
    ('2',  19, 'a2', 'b2', '2014-10-06 00:00:00'),
    ('3',  85, 'a3', 'b3', '2014-10-07 00:00:00'),
    ('4',  11, 'a1', 'b4', '2014-10-13 00:00:00'),
    ('5',  2,  'a2', 'b5', '2014-10-14 00:00:00'),
    ('6',  50, 'a3', 'b5', '2014-10-15 00:00:00'),
    ('7',  787323, 'a1', 'b6', '2014-10-17 00:00:00'),
    ('8',  33, 'a2', 'b8', '2014-10-18 00:00:00'),
    ('9',  14, 'a3', 'b9', '2014-10-19 00:00:00'),
    ('10', 11, 'a4', 'b10', '2014-10-19 00:00:00'),
    ('11', 1628, 'a1', 'b11', '2014-10-25 00:00:00'),
    ('13', 101, 'a2', 'b11', '2014-10-25 00:00:00');

输出示例:

Date       | # Active users
-----------+---------------
10-01-2014 | 600
10-02-2014 | 703
10-03-2014 | 891

以下是我尝试查找特定日期(例如 2014 年 1 月 10 日)的活跃用户数量的方法:

SELECT count(*)
FROM
  (SELECT accounts_id
   FROM requests
   WHERE "date" BETWEEN '2014-10-01'::date - interval '2 weeks' AND '2014-10-01'::date - interval '1 week'
   GROUP BY accounts_id HAVING sum(amount) > 10) week_1
JOIN
  (SELECT accounts_id
   FROM requests
   WHERE "date" BETWEEN '2014-10-01'::date - interval '3 weeks' AND '2014-10-01'::date - interval '2 week'
   GROUP BY accounts_id HAVING sum(amount) > 10) week_2 ON week_1.accounts_id = week_2.accounts_id
JOIN
  (SELECT accounts_id
   FROM requests
   WHERE "date" BETWEEN '2014-10-01'::date - interval '4 weeks' AND '2014-10-01'::date - interval '3 week'
   GROUP BY accounts_id HAVING sum(amount) > 10) week_3 ON week_2.accounts_id = week_3.accounts_id
JOIN
  (SELECT accounts_id
   FROM requests
   WHERE "date" BETWEEN '2014-10-01'::date - interval '5 weeks' AND '2014-10-01'::date - interval '4 week'
   GROUP BY accounts_id HAVING sum(amount) > 10) week_4 ON week_3.accounts_id = week_4.accounts_id

由于这只是获取 1 天号码的查询,因此我需要随着时间的推移每天获取该号码。我认为这个想法是进行连接来获取日期,所以我尝试做这样的事情:

SELECT week_1."Date_series",
       count(*)
FROM
  (SELECT to_char(DAY::date, 'YYYY-MM-DD') AS "Date_series",
          accounts_id
   FROM generate_series('2014-10-01'::date, CURRENT_DATE, '1 day') DAY, requests
   WHERE to_char(DAY::date, 'YYYY-MM-DD')::date BETWEEN requests.date::date - interval '2 weeks' AND requests.date::date - interval '1 week'
   GROUP BY "Date_series",
            accounts_id HAVING sum(amount) > 10) week_1
JOIN
  (SELECT to_char(DAY::date, 'YYYY-MM-DD') AS "Date_series",
          accounts_id
   FROM generate_series('2014-10-01'::date, CURRENT_DATE, '1 day') DAY, requests
   WHERE to_char(DAY::date, 'YYYY-MM-DD')::date BETWEEN requests.date::date - interval '3 weeks' AND requests.date::date - interval '2 week'
   GROUP BY "Date_series",
            accounts_id HAVING sum(amount) > 10) week_2 ON week_1.accounts_id = week_2.accounts_id
AND week_1."Date_series" = week_2."Date_series"
JOIN
  (SELECT to_char(DAY::date, 'YYYY-MM-DD') AS "Date_series",
          accounts_id
   FROM generate_series('2014-10-01'::date, CURRENT_DATE, '1 day') DAY, requests
   WHERE to_char(DAY::date, 'YYYY-MM-DD')::date BETWEEN requests.date::date - interval '4 weeks' AND requests.date::date - interval '3 week'
   GROUP BY "Date_series",
            accounts_id HAVING sum(amount) > 10) week_3 ON week_2.accounts_id = week_3.accounts_id
AND week_2."Date_series" = week_3."Date_series"
JOIN
  (SELECT to_char(DAY::date, 'YYYY-MM-DD') AS "Date_series",
          accounts_id
   FROM generate_series('2014-10-01'::date, CURRENT_DATE, '1 day') DAY, requests
   WHERE to_char(DAY::date, 'YYYY-MM-DD')::date BETWEEN requests.date::date - interval '5 weeks' AND requests.date::date - interval '4 week'
   GROUP BY "Date_series",
            accounts_id HAVING sum(amount) > 10) week_4 ON week_3.accounts_id = week_4.accounts_id
AND week_3."Date_series" = week_4."Date_series"
GROUP BY week_1."Date_series"

然而,我认为我没有得到正确的答案,我也不知道为什么。非常感谢任何提示/指导/指示! :) :)

附言。我正在使用 Postgres 9.3


这是一个很长的答案,如何使您的查询简短。 :)

Table

在我的表上构建(在您提供不同的表定义之前(odd!) 数据类型:

CREATE TABLE requests (
   id           int
 , accounts_id  int  -- (id of the user)
 , recipient_id int  -- (id of the recipient)
 , date         date -- (date that the request was made in YYYY-MM-DD)
 , amount       int  -- (# of requests by accounts_id for the day)
);

指定日期的活跃用户

“活跃用户”列表某一天:

SELECT accounts_id
FROM  (
   SELECT w.w, r.accounts_id
   FROM  (
      SELECT w
           , day - 6 - 7 * w AS w_start
           , day     - 7 * w AS w_end   
      FROM  (SELECT '2014-10-31'::date - 1 AS day) d  -- effective date here
           , generate_series(0,3) w
      ) w
   JOIN   requests r ON r."date" BETWEEN w_start AND w_end
   GROUP  BY w.w, r.accounts_id
   HAVING sum(r.amount) > 10
   ) sub
GROUP  BY 1
HAVING count(*) = 4;

Step 1

在最里面子查询w(对于“周”)从 4 周的兴趣中建立界限CROSS JOIN给定日期 - 1 的输出为generate_series(0-3).

添加/减去天数date(不是来自时间戳!)只需加/减integer数字。表达方式day - 7 * w从给定日期减去 0-3 乘以 7 天,得出end每周的日期(w_end).
分别减去 6 天(而不是 7 天!)来计算各自的start (w_start).
另外,保留周数w(0-3)用于以后的聚合。

Step 2

In 子查询sub连接来自的行requests到 4 周的集合,其中日期位于开始日期和结束日期之间。GROUP BY周数waccounts_id.
只有请求总数超过 10 的周才有资格。

Step 3

In the outer SELECT计算每个用户的周数(accounts_id) 合格的。必须为 4 才有资格成为“活跃用户”

每日活跃用户数

This is dynamite.
封装在一个简单的 SQL 函数中以简化一般使用,但查询也可以单独使用:

CREATE FUNCTION f_active_users (_now date = now()::date, _days int = 3)
  RETURNS TABLE (day date, users int) AS
$func$
WITH r AS (
   SELECT accounts_id, date, sum(amount)::int AS amount
   FROM   requests
   WHERE  date BETWEEN _now - (27 + _days) AND _now - 1
   GROUP  BY accounts_id, date
   )
SELECT date + 1, count(w_ct = 4 OR NULL)::int
FROM  (
   SELECT accounts_id, date
        , count(w_amount > 10 OR NULL)
                         OVER (PARTITION BY accounts_id, dow ORDER BY date DESC
                         ROWS BETWEEN CURRENT ROW AND 3 FOLLOWING) AS w_ct
   FROM  (
      SELECT accounts_id, date, dow   
           , sum(amount) OVER (PARTITION BY accounts_id ORDER BY date DESC
                         ROWS BETWEEN CURRENT ROW AND 6 FOLLOWING) AS w_amount
      FROM  (SELECT _now - i AS date, i%7 AS dow
             FROM   generate_series(1, 27 + _days) i) d -- period of interest
      CROSS  JOIN (
             SELECT accounts_id FROM r
             GROUP  BY 1
             HAVING count(*) > 3 AND sum(amount) > 39  -- enough rows & requests
             AND    max(date) > min(date) + 15) a      -- can cover 4 weeks
      LEFT   JOIN r USING (accounts_id, date)
      ) sub1
   WHERE date > _now - (22 + _days)  -- cut off 6 trailing days now - useful?
   ) sub2
GROUP  BY date
ORDER  BY date DESC
LIMIT  _days
$func$ LANGUAGE sql STABLE;

该函数需要任意一天(_now),默认为“今天”,以及天数 (_days) 结果中,默认为 3。称呼:

SELECT * FROM f_active_users('2014-10-31', 5);

或者不带参数使用默认值:

SELECT * FROM f_active_users();

方法是与第一个查询不同.

SQL小提琴包含表定义的查询和变体。

Step 0

在 CTE 中r每个预聚合金额(accounts_id, date)仅适用于感兴趣的时期,以获得更好的性能。该表仅被扫描once,建议的索引(见下文)将在此处生效。

Step 1

在内部子查询中d生成必要的天数列表:27 + _days行,其中_days是输出中所需的行数,有效为 28 天或更长。
在此过程中,计算一周中的哪一天(dow) 用于步骤 3 中的聚合。i%7与每周间隔一致,查询适用于any不过,间隔。

在内部子查询中a生成唯一的用户列表(accounts_id) 存在于 CTE 中r并通过一些初步的表面测试(足够的行跨越足够的时间和足够的总请求)。

Step 2

生成笛卡尔积d and a with a CROSS JOIN具有每个相关用户的每个相关日期一行. LEFT JOIN to r附加请求数量(如果有)。不WHERE在这种情况下,我们希望每天都有结果,即使根本没有活跃用户。

计算过去一周的总金额(w_amount)在同一步骤中使用窗口函数具有定制框架.例子:

  • 如何在窗口函数中使用环形数据结构

Step 3

现在切断最后6天;这是optional并且可能会或可能不会帮助性能。测试一下:WHERE date >= _now - (21 + _days)

计算满足最低金额的周数(w_ct)在类似的窗口函数中,这次划分为dow另外,框架中仅包含过去 4 周的相同工作日(包含过去一周的总和)。 表达方式count(w_amount > 10 OR NULL)仅计算请求数超过 10 的行。详细解释:

  • 在同一 SELECT sql 查询中从 SUM() 计算百分比

Step 4

在外层SELECT通过...分组date并对过去 4 周的用户进行计数(count(w_ct = 4 OR NULL))。日期加 1 以补偿偏差 1,ORDER and LIMIT到要求的天数。

业绩与展望

这两个查询的完美索引是:

CREATE INDEX foo ON requests (date, accounts_id, amount);

性能应该不错,但是使用即将推出的 Postgres 会更好9.4,由于新的移动聚合支持:

移动聚合支持在 Postgres Wiki 中。
9.4 手册中的移动聚合

旁白:不要打电话timestamp“日期”列,它是timestamp, not a date。更好的是,永远不要使用基本类型名称,例如date or timestamp作为标识符。曾经。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

每日查询计数,并具有多周的日期限制 的相关文章

  • 如何查找 PostgreSQL 数据库的上次更新时间?

    我正在使用一个批量更新的 postgreSQL 数据库 我需要知道数据库 或数据库中的表 上次更新或修改的时间 两者都可以 我看到 postgreSQL 论坛上有人建议使用日志记录并查询日志 这对我不起作用 因为我无法控制客户端代码库 你可
  • 模式更新后 jOOQ 生成的类的运行时验证?

    我用org jooq util DefaultGenerator在构建过程中生成 jOOQ 类来表示我的数据库模式 当应用程序运行时 架构预计会在应用程序不知情的情况下发生更改 此类更改可能与已生成的代码兼容 也可能不兼容 如何在运行时检测
  • 如何将日期字符串解析为Date? [复制]

    这个问题在这里已经有答案了 如何将下面的日期字符串解析为Date object String target Thu Sep 28 20 29 30 JST 2000 DateFormat df new SimpleDateFormat E
  • 使用 Spark DataFrame 获取组后所有组的 TopN

    我有一个 Spark SQL DataFrame user1 item1 rating1 user1 item2 rating2 user1 item3 rating3 user2 item1 rating4 如何按用户分组然后返回TopN
  • 使用 MS Access 获取行的第一个实例

    EDITED 我有这个查询 我想SELECT表中记录的第一个实例petTable SELECT id pet ID FIRST petName First Description FROM petTable GROUP BY pet ID
  • 如何在SSRS中的表上创建热图?

    如何在 SSRS 中创建这样的内容 颜色将根据行中的值 承销商 从红色变为绿色 所有这些都在一个组中 您可以通过右键单击各个单元格并根据表达式设置填充颜色来完成此操作 In the Image below I ve mistakingly
  • SQL参数化查询不显示结果

    我的 DataAcess 类中有以下函数 但它没有显示任何结果 我的代码如下 public List
  • 获取家庭成员

    假设以下家庭 其构建架构是 create table PersonConn child int parent int insert into PersonConn values 1 2 insert into PersonConn valu
  • 如何使用 MySQL 的 LOAD DATA LOCAL INFILE 在导入 CSV 时将字符串日期更改为 MySQL 日期格式

    我正在使用 MySQL 的 LOAD DATA LOCAL INFILE SQL 语句将数据从 CSV 文件加载到现有数据库表中 下面是一个 SQL 语句示例 LOAD DATA LOCAL INFILE file csv INTO TAB
  • 在 Rails 中禁用连接池以使用 PgBouncer

    我们有一个 Ruby on Rails 4 2 8 项目 可以访问大型 PostgreSQL 数据库 我们将使用 PgBouncer 添加一个新的连接池服务器 由于 PgBouncer 将处理数据库连接池 我们是否需要关闭 Rails 自动
  • 如何使用PostGIS将多边形数据转换为线段

    我在 PostgreSQL PostGIS 中有一个多边形数据表 现在我需要将此多边形数据转换为其相应的线段 谁能告诉我如何使用 PostGIS 查询进行转换 提前致谢 一般来说 将多边形转换为线可能并不简单 因为没有一对一的映射 http
  • 为什么这会返回资源 id #2? [复制]

    这个问题在这里已经有答案了 可能的重复 我如何从 PHP 中的 MySql 响应中 回显 资源 id 6 https stackoverflow com questions 4290108 how do i echo a resource
  • 拆分列中的字符串并在列中添加值

    我有一个包含几行数据的表 如下所示 16 W 2 Work ALBO 00 Proposal ALxO Amendement 1 20091022 signed pdf 17 W 2 Work ALBO 00 Proposal Level1
  • SQL 删除表并重新创建并保留数据

    在我们最初的设计中 我们搞砸了表中的外键约束 现在表已充满数据 我们无法在不删除表中所有记录的情况下更改它 我能想到的唯一解决方案是创建一个备份表并将所有记录放在那里 然后删除所有记录 更改表并开始将它们添加回来 还有其他 更好 的想法吗
  • 在sqlite SQL语句中与order by子句结合使用limit

    下面的两条 SQL 语句总是会产生相同的结果集吗 1 SELECT FROM MyTable where Status 0 order by StartTime asc limit 10 2 SELECT FROM SELECT FROM
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • sql server 按组排名

    问题看似简单 但我却无法理解 这是针对 sql 服务器的 what I have in a table What I need as a output cksum id cksum id 2162514679 204 2162514679
  • 用户登录时的 Postgresql 触发器

    我正在尝试找出一种方法来了解用户何时登录 Postgres 数据库 有没有办法定义用户登录数据库时触发的触发器 或者是否有一个表或系统视图在任何人登录数据库时都会更新 登录钩子 https github com splendiddata l
  • 使用 where 进行 select 语句时,HSQLDB 用户缺乏权限或未找到对象错误

    我的数据库使用 SQuirrel SQL 客户端版本 3 5 3 和 HSQLDB 我已经能够为其指定相应的驱动程序 内存中 并创建一个别名 我创建了一个表 CREATE TABLE ENTRY NAME VARCHAR 100 NOT N
  • 在 SQL 数据库中存储“列表”的最正确方法是什么?

    因此 我读了很多关于如何将多个值存储到一个列中是一个坏主意 并且违反了数据标准化的第一条规则 令人惊讶的是 这不是 不要谈论数据标准化 所以我需要一些帮助 目前我正在为我工 作的地方设计一个 ASP NET 网页 我想根据此人所属的 Act

随机推荐

  • 如何删除 XYLineAndShapeRenderer 中的点?

    我正在使用 JFreeChart 在 Java 中制作一个应用程序 它显示 XY 折线图 问题是它显示了线上数据集的每个点 而我不想显示这些点 关于如何删除这些点或使它们不可见有什么想法吗 这是一个示例屏幕截图 这是代码 JFrame fr
  • 如何用Java将日期插入MySQL数据库表?

    如何将没有时间的日期插入 MySQL 数据库表 我尝试了这些代码 但出现以下异常 com mysql jdbc exceptions jdbc4 MySQLSyntaxErrorException You have an error in
  • 使用 python 发送电子邮件,使用 csv 数据作为正文

    我正在使用 csv 库将数据提取到电子邮件正文中 我正在从 csv 中提取正文的某些列 我正在使用垃圾 Gmail 帐户进行测试 我只是对如何使用 for 循环感到困惑 如果我是正确的 您需要一个 for 循环来读取行 然后需要一个 for
  • 当针对“未定义”进行测试时,RegExp 给出了意外的结果

    我正在建造一个密码强度验证器检查密码是否包含小写和大写字符 我为此使用正则表达式 并在提供密码字符串时得到意外结果不明确的 请参阅下面的屏幕截图 我希望两张支票都能退回false 但第一个返回true Why does the first
  • 如何通过单击通知来关闭我的应用程序的任何活动?

    当我单击通知时 应用以下操作 intent setFlags Intent FLAG ACTIVITY NEW TASK Intent FLAG ACTIVITY CLEAR TOP startActivity intent 在应用程序的所
  • 使用 bash 读取两个文件的嵌套循环[重复]

    这个问题在这里已经有答案了 我目前正在尝试使用以下代码来合并两个输入文件 for i in cat file1 do for j in cat file2 do printf s s n i j done done 给定文件创建如下 pri
  • 将“mut”放在变量名之前和“:”之后有什么区别?

    以下是我在 Rust 文档中看到的两个函数签名 fn modify foo mut foo Box
  • Google Cloud Vertex AI - 模型不支持 400“dedicated_resources”

    我正在尝试使用 Python SDK 在 Google Cloud Platform 上部署通过 Vertex AI 训练的文本分类模型 from google cloud import aiplatform import os os en
  • Postgres:在 int 数组中查找最大值?

    使用 Postgres 9 3 有人可以解释一下为什么我不能直接在未嵌套的数组上使用 max 函数吗 据我了解 unnest 函数返回一个 setof 就像 select 语句一样 那么为什么这个查询的简短版本不起作用呢 我在概念上遗漏了一
  • 哪里是保存用户上传的图像的最佳位置

    我有一个显示画廊的网站 用户可以从网络上传自己的内容 通过输入 URL 或从计算机上传图片 我将 URL 存储在数据库中 这对于第一个用例来说效果很好 但如果用户从计算机上传 我需要弄清楚在哪里存储实际图像 这里有什么建议或关于我应该存储这
  • 如何在 Java 中初始化字节数组?

    我必须在 java 中以字节数组形式存储一些常量值 UUID 我想知道初始化这些静态数组的最佳方法是什么 这就是我目前正在做的 但我觉得一定有更好的方法 private static final byte CDRIVES new byte
  • 将 java.sql.Timestamp 转换为即时时间

    从我的数据库中我检索值如下 20 DEC 17 10 15 53 000000000 AM 我想要上面的java sql Timestamp转换为即时时间 2017 12 20T10 15 53Z 我尝试使用当前时间戳 Timestamp
  • rasa_nlu如何使用lookup_tables进行实体提取?

    我正在尝试使用 rasa nlu 和 rasa core 开发一个聊天机器人 但我没有得到 rasa nlu 如何使用 Lookup tables 进行实体提取的链接 我已经经历过 http blog rasa com improving
  • 使用 WMI 枚举音频输入设备

    我在我的 C 项目中使用 NAudio 我正在寻找一种枚举音频输入设备 麦克风等 的方法 这样我就可以获得它们的全名 不仅仅是我可以从 NAudio 获得的 31 个字符的长名称 我浏览了一些帖子 其中人们使用 WMI 枚举音频输出设备 M
  • 为什么这有效?删除多个 from 无子查询

    我不确定这是否是 SQL Server 2012 中的错误 我有一个简单的查询 DELETE FROM TABLE1 FROM TABLE2 WHERE TABLE1 COL1 1 在SSMS中 这段代码解析没有错误 并从Table1没有错
  • 如何在 WPF 中操作另一个类的窗口对象

    我是 WPF 和 C 新手 我了解很多 VB NET 并且习惯了调用文本框等表单对象的方式 我从另一个表单调用它 现在 我正在使用WPF 我很困惑 因为我有一个主窗口 我想从类将项目添加到主窗口中的列表框 在VB Net中 就是这样 IN
  • 当不在 python 中的正确包中时,不会捕获异常

    编辑 好的 我成功地隔离了该错误以及重现该错误的准确 完整的代码 但它要么是设计使然 要么是 python 中的错误 创建两个兄弟包 admin General 每个都有自己的 init py 当然 包装内admin将以下代码放入文件 te
  • 轻松使用 ASP.NET Identity 作为角色提供者

    我刚刚花了两天时间研究并使用现有数据库实现新的 ASP NET Identity 系统 更多信息请参见这里 将 ASP NET Identity 集成到现有的 DbContext 中 现在 我有一份工作UserStore and RoleS
  • 从 Kafka 消费失败迭代器处于失败状态

    我在使用来自 kafka 的消息时遇到异常 org springframework messaging MessagingException Consuming from Kafka failed nested exception is j
  • 每日查询计数,并具有多周的日期限制

    我正在尝试每天查找 个活跃用户 用户在创建后即处于活动状态多于每周 10 个请求 共 4 个连续几周 IE 2014 年 10 月 31 日 如果用户在以下时间段内每周发出的请求总数超过 10 个 则该用户处于活动状态 2014年10月24