【问题标题】:How to select only those records which are present in given all DATE range如何仅选择给定所有 DATE 范围中存在的那些记录
【发布时间】:2021-03-27 01:10:54
【问题描述】:

我想只选择所有日期都存在且重复数据计数的数据。

示例我的表数据是:

user_id row_created
8SRWS3hMR 2020-12-14 00:13:31
8SRWS3hMR 2020-12-14 00:35:06
8SRWS3hMR 2020-12-14 12:11:37
8SRWS3hMR 2020-12-14 13:16:27
8SRWS3hMR 2020-12-14 16:30:00
8SRWS3hMR 2020-12-14 19:25:11
8SRWS3hMR 2020-12-14 19:27:07
8SRWS3hMR 2020-12-15 17:14:06
8SRWS3hMR 2020-12-16 14:53:54

如果我选择2020-12-142020-12-17 之间的日期范围,那么输出应该为空。

如果我选择2020-12-142020-12-16 之间的日期范围,那么输出应该低于

user_id total row_created
8SRWS3hMR 7 2020-12-14 00:13:31
8SRWS3hMR 1 2020-12-15 17:14:06
8SRWS3hMR 1 2020-12-16 14:53:54

我试过下面的查询

select user_id, count(user_id) as total, row_created from reward
where user_id = '8SRWS3hMR' AND DATE(row_created) BETWEEN '2020-12-14' AND '2020-12-17'
group by DATE(row_created);

但根据我的要求,输出应该为 null,因为在 BETWEEN 日期范围内我已经通过 '2020-12-17'

请忽略语法错误。

【问题讨论】:

    标签: mysql sql


    【解决方案1】:

    您可以按如下方式使用HAVING 子句:

    SELECT USER_ID,
           COUNT(USER_ID) AS TOTAL,
           ROW_CREATED
      FROM REWARD
     WHERE USER_ID = '8SRWS3hMR'
       AND DATE(ROW_CREATED) BETWEEN '2020-12-14' AND '2020-12-17'
     GROUP BY DATE(ROW_CREATED) 
     HAVING COUNT(DISTINCT DATE(ROW_CREATED)) = datediff('2020-12-17', '2020-12-14') + 1;
    

    --更新

    SELECT * FROM
    (SELECT USER_ID,
           COUNT(USER_ID) AS TOTAL,
           ROW_CREATED,
           COUNT(DISTINCT DATE(ROW_CREATED)) OVER (PARTITION BY USER_ID) AS CNT
      FROM REWARD
     WHERE USER_ID = '8SRWS3hMR'
       AND DATE(ROW_CREATED) BETWEEN '2020-12-14' AND '2020-12-17'
     GROUP BY USER_ID, DATE(ROW_CREATED) 
    ) T WHERE CNT = datediff('2020-12-17', '2020-12-14') + 1
    

    【讨论】:

    • 没用。即使我将日期从 14 日传递到 16 日,我也没有得到任何回应。如果我通过了 14 到 16 之间的日期,它应该会出现。只有在我超过 17 岁的情况下才会出现,因为任何用户的 17 记录都不可用。
    • 我认为这个想法很明确吧?请尝试使用这个逻辑。否则我会照顾它,但在你玩它之后一次
    • 我玩但没有得到预期的输出。
    • 去掉having子句会有什么结果?
    • 如果删除 having 子句,我将得到日期 14/15/16 的结果。
    【解决方案2】:

    这有点复杂,因为您需要按日期汇总。您可以使用窗口函数:

    SELECT r.*
    FROM (SELECT USER_ID, DATE(ROW_CREATED) as date, COUNT(*) AS TOTAL,
                 MIN(ROW_CREATED) as ROW_CREATED,
                 COUNT(*) OVER (PARTITION BY USER_ID) as num_days,
                 DATEDIFF(x.end_date, x.start_date) + 1 AS total_days
          FROM REWARD R CROSS JOIN
               (SELECT DATE('2020-12-14') as START_DATE, DATE('2020-12-17') as END_DATE
               ) params
          WHERE USER_ID = '8SRWS3hMR' AND
                ROW_CREATED >= x.start_date AND
                ROW_CREATE <= x.end_date + interval 1 day
          GROUP BY DATE(ROW_CREATED) 
         ) R
    WHERE num_days = total_days;
    

    子查询按天汇总。它包括两个方面:

    • USER_ID 的不同天数。
    • 总天数。

    为避免多次输入相同的日期,这些日期在子查询中定义。另请注意,日期比较已重新安排。不使用DATE() 函数,而是使用不等式。这使得表达式与索引更兼容。

    【讨论】:

      【解决方案3】:

      选择 user_id,count(user_id) 作为总数,row_created from reward 其中 user_id = '8SRWS3hMR' AND DATE(row_created) >= '2020-12-14' AND DATE(row_created) = DATEDIFF(row_created, '2020-12-17')

      【讨论】:

      • Siva,您的查询对我不起作用。如果特定用户的记录每天都存在,我想要该用户。就像如果每天从 14 点到 17 点都有可用的记录,那么只有该用户会进入输出。如果他错过了任何一天,那么它不应该输出。
      猜你喜欢
      • 1970-01-01
      • 2017-05-25
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多