【问题标题】:Filter Context and Group by in SQL在 SQL 中过滤上下文和分组依据
【发布时间】:2021-08-17 02:38:43
【问题描述】:

考虑具有 2 列的表格,每次用户登录时都会有一个新行。(大约 1000 万行,并且可以有重复,因为用户每月可以多次登录)

Sign in Month MemberID
2020-10 1000000
2020-12 1000001

现在要找出每个月的唯一用户,我可以使用以下查询。

Select Sign_in_Month, count(distinct(memberid)) as unique_users from table group by Sign_in_Month

但我想将第一个查询中的不同计数进一步分解为 2 个同类群组,其中用户要么在过去 3 个月前登录,要么没有登录。 (2020 年 10 月为 2020 年 7 月至 2020 年 9 月,2020 年 9 月为 2020 年 6 月至 8 月

我曾经通过 DAX 在 powerBI 中执行此操作,这对于过滤上下文很容易,但我不确定如何在 SQL 中实现。

想要的结果

Sign in Month Total Unique Users Unique Users who signed in in the last 3 months Unique Users who did not sign in in the last 3 months
2020-10 4000 3000 1000
2020-11 5000 2500 2500
2020-12 3500 1500 2000

最后 2 列应与第二列相加。

我如何创建某种指标,说明会员在过去 3 个月内购物的地点参考该特定月份?

谢谢

【问题讨论】:

  • 用您正在使用的数据库标记您的问题。

标签: sql sql-server dax


【解决方案1】:

我会这样处理:

  • 每月获取唯一价值。
  • 使用lag() 查看上个月有人登录的时间。
  • 比较时差。

为方便起见,我会将sign_in_month 转换为日期:

select sign_in_date,
       count(*) as num_members,
       sum(case when prev_sign_in_date >= dateadd(month, -4, sign_in_date)
                then 1 else 0 
           end) as num_members_who_signed_in
from (select t.memberId, v.sign_in_date,
             lag(v.sign_in_date) over (partition by t.memberId order by v.sign_in_date) as prev_sign_in_date
      from t cross apply
           (values (convert(date, t.sign_in_month, '-01'))
           ) v(sign_in_date)
      group by t.memberId, v.sign_in_date
     ) t
group by sign_in_date;

请注意,不再需要 count(distinct),因为子查询会处理这个问题。

【讨论】:

  • 谢谢@Gordon Linoff - 使用滞后的子查询正是我想要的。
【解决方案2】:

你可以试试下面的脚本-

注意:语法是MSSQL,但逻辑是全局的

select 
sign_in_month,
count(distinct MemberId) as total_unique_user,
count(
    CASE 
        WHEN CAST(sign_in_month+'-01' as Date) >= DATEADD(mm,-4,getdate()) then MemberId
        else null
    end
) as last_3_month,
count(
    CASE 
        WHEN CAST(sign_in_month+'-01' as Date) < DATEADD(mm,-4,getdate()) then MemberId
        else null
    end
) as before_3_month

from your_table_name
GROUP BY sign_in_month

【讨论】:

  • 不会使用 getdate 只是引用今天的日期,而是从登录发生的日期开始?
  • Getdate() 是今天(系统/服务器)
  • 我选择了另一个答案作为解决方案,因为它更接近我想要实现的目标,但感谢您的意见。
  • 我认为投赞成票是表达感谢的更好方式 :)
猜你喜欢
  • 1970-01-01
  • 2022-01-12
  • 2022-12-06
  • 1970-01-01
  • 2021-09-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多