SQL - 单个查询

时间:2018-01-18 21:47:00

标签: sql teradata data-manipulation

我有一个客户行为的SQL数据库,一个客户由UniqueId定义,一个动作被赋予一个行动时间戳的日期和时间。用户可以在任何一天执行多个操作:

UniqueID | actionDate | actionTime |
   1       17-01-18     13:01
   1       17-01-18     13:15
   2       17-01-18     13:15
   1       18-01-18     12:56

我希望理想地在单个查询中理解数据库中的多个内容。

  1. 第一个是每个uniqueId在给定时间段(日,周,月)内执行了多少次操作,因此对于上面的示例,对于17-01-18的id1,将计数为2 ,18-01-18的计数为1,并假设它们是本周唯一的两个动作,对于那一周的id为1的计数为3。

  2. 在有多个操作的日子(上例中为17-01-18)我想了解一天中的操作分布,更重要的是了解一段时间内发生的操作数量一个小时在这种情况下,id想要了解id为1的13:00到14:00之间发生的2个动作,但是其他23个小时有0个动作。

  3. 最终目标是建立一个回顾三个月的时间序列,并能够查看每个唯一ID的每月,每周和每日重要的每日行动计数。

    期望的结果可能如下所示:

    ID | M1W1D1H1|M1W1D1H2|->|M1W1D1H13|->|M1W1D2H12|
       1   0         0            2             1
       2   0         0            1             0
    

    M =月,W =周,D =日,H =小时。 AC = ActionCount

    所以上面显示在第1个月,第1周,第1天,第1小时,id1没有动作。第一个动作是在M1W1D1H13,其中有两个动作。接下来的行动是在W1,M1的D2上。然后可以汇总以获得相应的每周每日每月操作。很多0动作的结果都相当稀疏。

    任何帮助和指导表示赞赏。

1 个答案:

答案 0 :(得分:1)

如果我理解您的问题,您会在标准化数据结构中找到包含日期和时间详细信息的ID。但是,您希望对此数据进行非规范化,以便在您希望的条件下,每个ID只有一行汇总。

要做到这一点,你可以使用一个简单的group by并将你的聚合嵌套到case语句中,使它们符合你想要的列范围。如果您不能对时间片进行硬编码,并且需要尽可能动态,但我需要有关您的要求的更多信息。您还可以将案例语句嵌套到case语句中,并使用派生表来进一步启用更复杂的规则。

所以,使用你的例子......

sel
  UniqueID 
, sum(
  case when actionDate between <someDate> and <someDate> then 1
  end) as evnt_cnt_in_range01
, count(distinct(
  case when actionDate between <someDate> and <someDate> then actionDate
  end)) as uniq_dates_in_range01
, min(
  case when actionDate between <someDate> and <someDate> then actionTime
  end) as earliest_action_in_range01
, max(
  case when actionDate between <someDate> and <someDate> then actionTime
  end) as latest_action_in_range01
, max(
  case when actionDate between <someDate> and <someDate> then
    CASE WHEN actionTime > '12:00' THEN 1 ELSE 0 END -- I flip caps to keeps nests straight
  end) as cnt_after_noon_action_range1
FROM <sometable>
group by 1