在你提到的 SQL 查询中:
```sql
select id, stt dt, 1 p from test5
union
select id, edt dt, -1 p from test5
```
这里的 `p` 是一个人为添加的 **标志字段(或称为权重字段)**,用来表示某个时间点是“主播上线”还是“主播下线”。
---
### ✅ `p` 字段的作用解释如下:
- `p = 1`:表示在该时间点有一个主播 **开始直播(上线)**
- `p = -1`:表示在该时间点有一个主播 **结束直播(下线)**
这个技巧常用于解决“**最多重叠区间问题**”,比如求**同一时刻最多有多少个主播在线**。
我们将每个开播时间标记为 +1,关播时间标记为 -1,然后按时间顺序排序,对 `p` 值做累加(前缀和),就可以得到任意时刻正在直播的主播人数。
---
### 🔍 举个例子说明
原始数据:
| id | stt | edt |
|------|----------------------|----------------------|
|1001|2021-06-14 12:12:12|2021-06-14 18:12:12|
|1003|2021-06-14 13:12:12|2021-06-14 16:12:12|
转换后变成事件流(t1):
| id | dt | p |
|------|----------------------|----|
|1001|2021-06-14 12:12:12| 1 | ← 开播 +1
|1003|2021-06-14 13:12:12| 1 | ← 开播 +1
|1003|2021-06-14 16:12:12|-1 | ← 下播 -1
|1001|2021-06-14 18:12:12|-1 | ← 下播 -1
然后我们按照 `dt` 时间排序,并计算累计值(即当前在线主播数):
```text
时间 事件类型 当前人数变化 累计在线人数
2021-06-14 12:12:12 开播(id=1001) +1 1
2021-06-14 13:12:12 开播(id=1003) +1 2
2021-06-14 16:12:12 下播(id=1003) -1 1
2021-06-14 18:12:12 下播(id=1001) -1 0
```
所以最高同时在线人数是 **2人**。
---
### 📌 完整 SQL 思路(以 Hive/MySQL 为例)
```sql
-- 第一步:将开播和关播转为带符号的事件流
with events as (
select id, stt as dt, 1 as p from test5
union all
select id, edt as dt, -1 as p from test5
),
-- 第二步:按时间排序,注意时间相同时,优先处理上线再处理下线?实际建议:同时间先+1后-1
sorted_events as (
select dt, p
from events
order by dt, p desc -- 先处理 +1 再处理 -1,防止漏算峰值
)
-- 第三步:使用窗口函数累加 p,找出最大值
select max(online_cnt) as max_concurrent_streamers
from (
select
dt,
sum(p) over (order by dt, p desc rows between unbounded preceding and current row) as online_cnt
from sorted_events
) t;
```
> 💡 注意:这里用 `UNION ALL` 比 `UNION` 更高效,因为不需要去重。
---
### ❗关键点总结
- `p` 是一个虚拟的增量字段,用于统计人数变化。
- 把每一个“开始”看作 +1,“结束”看作 -1,构建时间轴上的变化事件。
- 对这些事件按时间排序并累加 `p`,就能得到每一时刻的在线人数。
- 最大累加值就是平台最高峰同时在线的主播人数。
---
### ✅ 示例 Python 实现(便于理解逻辑)
```python
from datetime import datetime
# 模拟数据
data = [
(1001, '2021-06-14 12:12:12', '2021-06-14 18:12:12'),
(1003, '2021-06-14 13:12:12', '2021-06-14 16:12:12'),
(1004, '2021-06-14 13:15:12', '2021-06-14 20:12:12'),
(1002, '2021-06-14 15:12:12', '2021-06-14 16:12:12'),
(1005, '2021-06-14 15:18:12', '2021-06-14 20:12:12'),
(1001, '2021-06-14 20:12:12', '2021-06-14 23:12:12'),
(1006, '2021-06-14 21:12:12', '2021-06-14 23:15:12'),
(1007, '2021-06-14 22:12:12', '2021-06-14 23:10:12'),
]
events = []
for row in data:
_id, stt_str, edt_str = row
stt = datetime.strptime(stt_str, '%Y-%m-%d %H:%M:%S')
edt = datetime.strptime(edt_str, '%Y-%m-%d %H:%M:%S')
events.append((stt, 1))
events.append((edt, -1))
# 排序:先按时间,再按 +1 在前、-1 在后
events.sort(key=lambda x: (x[0], -x[1]))
online = 0
max_online = 0
for time, delta in events:
online += delta
if online > max_online:
max_online = online
print("平台最高峰同时在线主播人数:", max_online)
```
输出结果为:
```
平台最高峰同时在线主播人数: 4
```
(你可以验证:在 `2021-06-14 15:18:12 ~ 16:12:12` 之间有 4 位主播同时在线)
---
###