HQL || SQL练习:根据四节气推算季节

  • 有一张用户骑车日期节气表dwd_ride_date_term_dd, 包含user_id(用户id)、ride_dt(骑行日期)以及dt_term(日期对应节气)
  • 如果用户当天多次骑行,该表只会记录一次
  • 如果骑行日不是立春、立夏、立秋、立冬这四个日期,那么该字段为NULL
  • 问题:请求出所有用户骑行日对应的季节(春、夏、秋、冬)

思路:

很明显,我们只要计算出立春、立夏、立秋、立冬四个节气的具体日期(开始日期和结束日期),然后和骑行日期进行比较即可:

  • 立春 <= date < 立夏 -> 春
  • 立夏 <= date < 立秋 -> 夏
  • 立秋 <= date < 立冬 -> 秋
  • 立冬 <= date < 立春 -> 冬
create table dwd_ride_date_term_dd (
user_id varchar(20),
ride_dt varchar(20),
dt_term varchar(20)
);
INSERT INTO dwd_ride_date_term_dd VALUES 
('001','20240101',NULL),
('001','20240203','立春'),
('001','20240311',NULL),
('001','20240401',NULL),
('001','20240505','立夏'),
('001','20240522',NULL),
('001','20240807','立秋'),
('001','20241028',NULL),
('001','20241107','立冬'),
('001','20241217',NULL),
('001','20250101',NULL),
('001','20250203','立春'),
('001','20250311',NULL),
('001','20250401',NULL),
('001','20250505','立夏'),
('001','20250522',NULL),
('001','20250807','立秋'),
('001','20251028',NULL),
('001','20251107','立冬'),
('001','20251217',NULL)
;
with t1 as (
    select 
        user_id,
        ride_dt as start_dt,
        dt_term,
        lead(ride_dt, 1, null) over(partition by user_id order by ride_dt) as end_dt
    from dwd_ride_date_term_dd
    where dt_term is not null
)
select 
    t2.user_id,
    t2.ride_dt,
    case  
        when t1.dt_term = '立春' then '春'
        when t1.dt_term = '立夏' then '夏'
        when t1.dt_term = '立秋' then '秋'
        when t1.dt_term = '立冬' then '冬'
    else '冬' end as season
from dwd_ride_date_term_dd t2
left join t1
on t1.user_id = t2.user_id
and t2.ride_dt >= t1.start_dt 
and (t2.ride_dt < t1.end_dt or t1.end_dt is null);

lead(ride_dt, 1, '20991231') over(partition by user_id order by ride_dt) as end_dt

优点:

  • 明确性:使用特定日期字符串作为默认值,使得end_dt字段总是有一个明确的值,这对于某些应用场景来说可能是必要的。
  • 兼容性:对于那些期望end_dt始终有一个有效日期的系统或应用,这种方法更符合预期。

缺点:

  • 假设依赖:这种方法依赖于特定的假设,即所有用户都至少有一次骑行记录,并且每个人都有一个明确的结束日期。这不总是成立,特别是在新用户或历史数据不完整的情况下。
  • 数据真实性:使用固定的日期字符串可能会掩盖实际的数据问题,比如说用户真正的最后一次活动日期是什么

lead(ride_dt, 1, null) over(partition by user_id order by ride_dt) as end_dt

优点:

  • 灵活性:允许end_dt字段为null,这使得处理缺失数据变得更加灵活。
  • 数据真实性:直接反映出某些用户可能没有明确的结束日期,这对于理解用户行为模式和数据完整性分析更有价值。

缺点:

  • 兼容性:对于那些要求end_dt必须有一个有效日期的系统或应用,这种方法可能不够理想,因为它允许end_dtnull
  • 额外的处理:在使用end_dt字段时,需要额外的逻辑来处理null值(语句末尾的(t2.ride_dt < t1.end_dt or t1.end_dt is null

你可能感兴趣的:(sql,数据库,大数据,hive)