【问题标题】:Get count of users till a given date获取到给定日期的用户数
【发布时间】:2018-03-27 09:22:38
【问题描述】:

我在连接中使用了以下两个表

TABLE1: rat_proj_duration_map
列: UID、Hour_val、month_val

TABLE2: 个用户
列: UID、状态、left_on

此处状态将包含文本('Act','InAct')

现在,我正在尝试获取按 month_val 字段分组的 UID 计数,如下所示

select count(r.uid) as cnt, r.month_val
from rat_proj_duration_map r
    inner join users u on r.uid = u.uid 
where  r.year_val = 2018 
group by r.month_val
order by month_val

上面的查询给出了按月计算的记录数。

但是,我试图忽略左侧日期(用户表中的 left_on)中的“未激活”用户(用户表中的状态字段)。

因此,如果用户留在“2018-03-27”,那么该用户记录应计算到 3 月,而不是在那之后。

要添加到我的查询的条件是什么

示例输出: 如果有 100 个用户记录和一个用户 left_on '2018-03-27' 状态为 'Inactivate' 那么我的结果应该如下所示

Count  Month_val
100      1
100      2
100      3
99       4
99       5
99       6
99       7
99       8
99       9
99       10
99       11
99       12

【问题讨论】:

  • 您的表rat_proj_duration_map 是某种日历表吗?我们无法运行您提供的查询,也无法访问您的对象。我所能告诉你的只是在你的WHERE 中添加一个进一步的子句。 也许 AND DATEPART(MONTH,u.dateleft) <= r.month_val(不知道哪个字段中有日期)?不过,该子句不会是 SARGable。
  • rat_proj_duration_map 包含整数形式的month_val
  • 是的,我知道,否则您将无法使用r.month_val。恐怕你的评论并没有告诉我关于这张桌子的任何其他信息。
  • Left_on 将在用户“未激活”时由日期时间戳填充,因此我必须忽略退出日期月份值中的用户数据

标签: sql sql-server date group-by


【解决方案1】:

根据每个项目的禁用日期过滤用户。您可以使用附加的连接子句(或在本例中为 WHERE)来执行此操作。

DECLARE @FilterYear INT = 2018

select 
    count(r.uid) as cnt, 
    r.month_val
from 
    rat_proj_duration_map r
    inner join users u on r.uid = u.uid 
where  
    r.year_val = @FilterYear AND
    (
        u.left_on IS NULL OR
        YEAR(u.left_on) > @FilterYear OR
        (YEAR(u.left_on) = @FilterYear AND R.month_val <= MONTH(u.left_on))
    )
group by 
    r.month_val
order by 
    month_val

请记住,我们是在比较年份和月份(没有日期)。您必须考虑当用户在月中停用时会发生什么。

【讨论】:

  • 谢谢,但您的 SQL 总是只给出三行(1 月、2 月、3 月)
  • @ManiMuthuPandi 已编辑,添加了对 left_on 空值的检查。请再运行一次。
  • 非常感谢,你在摇摆不定;是的,我需要它以月为基础而不是以日期为基础,所以如果用户在任何日期离开都没有问题
【解决方案2】:

你可以试试这个查询(代码中必要的 cmets):

select [count] - [left_count] from 
(
    select [left_month_val],
           --this will give amount of users left UP TO particular month
           SUM([left_count]) over (order by [left_month_val] rows between unbounded preceding and current row) [left_count]
    from (
        --here you count how many users left in particular months
        select DATEPART(month, [left_on]) [left_month_val], COUNT(*) [left_count]
        from [users]
        group by DATEPART(month, [left_on])
    ) [a]
) [u] join (
    --here you count how many users were there in particular months
    select [month_val], count(*) [count]
    from rat_proj_duration_map
    group by [month_val]
) [r] on [u].[left_month_val] = [r].[month_val]

另外,请记住,没有一个查询包含年份,因此您应该添加另一个分组变量。不幸的是,我无法亲自尝试,因为您没有提供示例数据。

【讨论】:

    【解决方案3】:

    我想你想要这个:

    SELECT COUNT(CASE WHEN u.status = 'InAct' AND u.left_on < DATEADD(month, month_val - 1, DATEADD(year, year_val - 1900, 0)) THEN NULL ELSE 1 END) AS cnt, r.month_val
    FROM rat_proj_duration_map r
    INNER JOIN users u ON r.uid = u.uid
    WHERE r.year_val = 2018
    GROUP BY r.year_val, r.month_val
    ORDER BY r.year_val, r.month_val
    

    表达式DATEADD(month, month_val - 1, DATEADD(year, year_val - 1900, 0)) 会将2018, 3 转换为2018-03-01。您不需要计算用户状态为非活动且用户在 year-month-01 之前离开的记录。

    SQL Fiddle with dummy data

    【讨论】:

    • 我认为您的查询没有选择 UID 的计数
    • @ManiMuthuPandi 已修复。
    • 如何从您的查询中获取不同的 UID
    • @ManiMuthuPandi 将 COUNT(CASE... THEN NULL ELSE 1 END) 更改为 COUNT(DISTINCT CASE... THEN NULL ELSE r.uid END)
    【解决方案4】:

    你可以试试这个

    select count(case when u.status='Act' then r.uid end) as cnt, r.month_val
    from rat_proj_duration_map r
    inner join users u on r.uid = u.uid 
    where  r.year_val = 2018 
    group by r.month_val
    order by month_val
    

    【讨论】:

    • 那行不通。一旦用户未标记为'Act',他们将在所有月份中获得折扣,而不仅仅是后续月份。
    猜你喜欢
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 2014-03-08
    相关资源
    最近更新 更多