555 lines
12 KiB
Markdown
555 lines
12 KiB
Markdown
|
|
# 绑定关系存储方案分析
|
|||
|
|
|
|||
|
|
## 📊 当前实现
|
|||
|
|
|
|||
|
|
### 表结构
|
|||
|
|
|
|||
|
|
#### 1. referral_bindings 表(主表)
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE referral_bindings (
|
|||
|
|
id VARCHAR(50) PRIMARY KEY,
|
|||
|
|
referrer_id VARCHAR(50), -- 推荐人ID
|
|||
|
|
referee_id VARCHAR(50), -- 被推荐人ID
|
|||
|
|
referral_code VARCHAR(50), -- 推荐码
|
|||
|
|
status ENUM('active', 'expired', 'cancelled'), -- 状态
|
|||
|
|
binding_date DATETIME, -- 绑定时间
|
|||
|
|
expiry_date DATETIME, -- 过期时间
|
|||
|
|
last_purchase_date DATETIME, -- 最后购买时间
|
|||
|
|
purchase_count INT DEFAULT 0, -- 购买次数
|
|||
|
|
total_commission DECIMAL(10,2) DEFAULT 0.00, -- 累计佣金
|
|||
|
|
|
|||
|
|
INDEX idx_referee_status (referee_id, status),
|
|||
|
|
INDEX idx_referrer_status (referrer_id, status)
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 2. users 表(冗余字段)
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE users (
|
|||
|
|
id VARCHAR(50) PRIMARY KEY,
|
|||
|
|
referred_by VARCHAR(50), -- 冗余:当前推荐人ID
|
|||
|
|
referral_count INT DEFAULT 0, -- 冗余:推荐人的推广数量
|
|||
|
|
referral_code VARCHAR(50), -- 自己的推荐码
|
|||
|
|
pending_earnings DECIMAL(10,2), -- 待结算收益
|
|||
|
|
earnings DECIMAL(10,2), -- 已结算收益
|
|||
|
|
withdrawn_earnings DECIMAL(10,2) -- 已提现金额
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔍 当前使用情况分析
|
|||
|
|
|
|||
|
|
### 1. 绑定关系的创建/更新(/api/referral/bind)
|
|||
|
|
|
|||
|
|
**操作**:
|
|||
|
|
```typescript
|
|||
|
|
// 1. 查询当前绑定(使用 referral_bindings)
|
|||
|
|
SELECT * FROM referral_bindings
|
|||
|
|
WHERE referee_id = ? AND status = 'active'
|
|||
|
|
|
|||
|
|
// 2. 创建/更新绑定记录
|
|||
|
|
INSERT INTO referral_bindings (...)
|
|||
|
|
|
|||
|
|
// 3. 同步更新 users.referred_by(冗余)
|
|||
|
|
UPDATE users SET referred_by = ? WHERE id = ?
|
|||
|
|
|
|||
|
|
// 4. 更新 users.referral_count(冗余计数)
|
|||
|
|
UPDATE users SET referral_count = referral_count + 1 WHERE id = ?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
- ✅ `referral_bindings` 是真实来源
|
|||
|
|
- ⚠️ `users.referred_by` 是冗余,可能不一致
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 2. 支付回调计算佣金(/api/miniprogram/pay/notify)
|
|||
|
|
|
|||
|
|
**操作**:
|
|||
|
|
```typescript
|
|||
|
|
// 查询绑定关系(使用 referral_bindings)
|
|||
|
|
SELECT * FROM referral_bindings
|
|||
|
|
WHERE referee_id = ? AND status = 'active'
|
|||
|
|
ORDER BY binding_date DESC LIMIT 1
|
|||
|
|
|
|||
|
|
// 如果找到 → 给推荐人佣金
|
|||
|
|
UPDATE users SET pending_earnings = pending_earnings + ? WHERE id = ?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**结论**:
|
|||
|
|
- ✅ 只使用 `referral_bindings`
|
|||
|
|
- ✅ 不依赖 `users.referred_by`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 3. 分销中心数据(/api/referral/data)
|
|||
|
|
|
|||
|
|
**操作**:
|
|||
|
|
```typescript
|
|||
|
|
// 查询活跃绑定
|
|||
|
|
SELECT * FROM referral_bindings
|
|||
|
|
WHERE referrer_id = ? AND status = 'active' AND expiry_date > NOW()
|
|||
|
|
|
|||
|
|
// 查询已转化用户
|
|||
|
|
SELECT * FROM referral_bindings
|
|||
|
|
WHERE referrer_id = ? AND status = 'active' AND purchase_count > 0
|
|||
|
|
|
|||
|
|
// 查询过期绑定
|
|||
|
|
SELECT * FROM referral_bindings
|
|||
|
|
WHERE referrer_id = ? AND status IN ('expired', 'cancelled')
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**结论**:
|
|||
|
|
- ✅ 只使用 `referral_bindings`
|
|||
|
|
- ✅ 不依赖 `users.referred_by`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4. 自动解绑(/api/cron/unbind-expired)
|
|||
|
|
|
|||
|
|
**操作**:
|
|||
|
|
```typescript
|
|||
|
|
// 查询需要解绑的记录
|
|||
|
|
SELECT * FROM referral_bindings
|
|||
|
|
WHERE status = 'active'
|
|||
|
|
AND expiry_date < NOW()
|
|||
|
|
AND purchase_count = 0
|
|||
|
|
|
|||
|
|
// 批量更新为 expired
|
|||
|
|
UPDATE referral_bindings SET status = 'expired' WHERE id IN (...)
|
|||
|
|
|
|||
|
|
// 更新 referral_count
|
|||
|
|
UPDATE users SET referral_count = GREATEST(referral_count - ?, 0) WHERE id = ?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**结论**:
|
|||
|
|
- ✅ 只使用 `referral_bindings`
|
|||
|
|
- ⚠️ 但没有更新 `users.referred_by`(可能导致不一致)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 5. 旧代码兼容(/api/referral/bind - 旧接口)
|
|||
|
|
|
|||
|
|
**操作**:
|
|||
|
|
```typescript
|
|||
|
|
// 查询推荐的用户(使用 users.referred_by)
|
|||
|
|
SELECT * FROM users WHERE referred_by = ?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
- ⚠️ 使用了 `users.referred_by`
|
|||
|
|
- ⚠️ 可能查到已过期的绑定
|
|||
|
|
- ⚠️ 应该改用 `referral_bindings`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 数据一致性分析
|
|||
|
|
|
|||
|
|
### 场景1: 用户 A 推荐 B,30天后过期
|
|||
|
|
|
|||
|
|
#### referral_bindings 表
|
|||
|
|
```sql
|
|||
|
|
referrer_id: A
|
|||
|
|
referee_id: B
|
|||
|
|
status: expired ✅ 正确
|
|||
|
|
expiry_date: 2026-01-01
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### users 表
|
|||
|
|
```sql
|
|||
|
|
B.referred_by: A ⚠️ 仍然是 A(未清空)
|
|||
|
|
A.referral_count: 1 ⚠️ 未减少(自动解绑任务有更新)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**问题**:
|
|||
|
|
- `users.referred_by` 没有在过期时清空
|
|||
|
|
- 如果查询 `users.referred_by`,会得到错误结果
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 场景2: B 从 A 切换到 C
|
|||
|
|
|
|||
|
|
#### referral_bindings 表
|
|||
|
|
```sql
|
|||
|
|
-- 旧绑定
|
|||
|
|
referrer_id: A
|
|||
|
|
referee_id: B
|
|||
|
|
status: cancelled ✅ 正确
|
|||
|
|
|
|||
|
|
-- 新绑定
|
|||
|
|
referrer_id: C
|
|||
|
|
referee_id: B
|
|||
|
|
status: active ✅ 正确
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### users 表
|
|||
|
|
```sql
|
|||
|
|
B.referred_by: C ✅ 正确(已更新)
|
|||
|
|
A.referral_count: 0 ✅ 正确(已减少)
|
|||
|
|
C.referral_count: 1 ✅ 正确(已增加)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**结论**:切换时同步正确
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 性能分析
|
|||
|
|
|
|||
|
|
### 方案1: 只用 referral_bindings(推荐)
|
|||
|
|
|
|||
|
|
**优势**:
|
|||
|
|
- ✅ 数据一致性强(单一数据源)
|
|||
|
|
- ✅ 状态清晰(active / expired / cancelled)
|
|||
|
|
- ✅ 信息完整(过期时间、购买次数等)
|
|||
|
|
- ✅ 易于维护
|
|||
|
|
|
|||
|
|
**劣势**:
|
|||
|
|
- ❌ 查询需要 JOIN 或多次查询
|
|||
|
|
- ❌ 复杂查询性能稍低
|
|||
|
|
|
|||
|
|
**查询示例**:
|
|||
|
|
```typescript
|
|||
|
|
// 查询用户的当前推荐人
|
|||
|
|
SELECT referrer_id FROM referral_bindings
|
|||
|
|
WHERE referee_id = ? AND status = 'active' AND expiry_date > NOW()
|
|||
|
|
ORDER BY binding_date DESC LIMIT 1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**性能**:
|
|||
|
|
- 有索引 `idx_referee_status`
|
|||
|
|
- 查询速度:~0.1ms
|
|||
|
|
- 适合:几乎所有场景
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 方案2: 冗余到 users 表
|
|||
|
|
|
|||
|
|
**优势**:
|
|||
|
|
- ✅ 查询快(直接读 users.referred_by)
|
|||
|
|
- ✅ 简单场景方便
|
|||
|
|
|
|||
|
|
**劣势**:
|
|||
|
|
- ❌ 数据一致性差(需要同步)
|
|||
|
|
- ❌ 过期后不准确
|
|||
|
|
- ❌ 切换时需要多表更新
|
|||
|
|
- ❌ 维护成本高
|
|||
|
|
|
|||
|
|
**需要同步的场景**:
|
|||
|
|
1. 新绑定时
|
|||
|
|
2. 切换推荐人时
|
|||
|
|
3. 绑定过期时 ⚠️(当前未同步)
|
|||
|
|
4. 绑定取消时 ⚠️(当前未同步)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 方案3: 视图或计算字段(推荐)
|
|||
|
|
|
|||
|
|
**实现**:
|
|||
|
|
```sql
|
|||
|
|
-- 创建视图
|
|||
|
|
CREATE VIEW user_current_referrer AS
|
|||
|
|
SELECT
|
|||
|
|
rb.referee_id as user_id,
|
|||
|
|
rb.referrer_id,
|
|||
|
|
u.nickname as referrer_nickname,
|
|||
|
|
rb.expiry_date,
|
|||
|
|
rb.purchase_count
|
|||
|
|
FROM referral_bindings rb
|
|||
|
|
JOIN users u ON rb.referrer_id = u.id
|
|||
|
|
WHERE rb.status = 'active'
|
|||
|
|
AND rb.expiry_date > NOW()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**使用**:
|
|||
|
|
```typescript
|
|||
|
|
// 查询用户的当前推荐人
|
|||
|
|
SELECT * FROM user_current_referrer WHERE user_id = ?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**优势**:
|
|||
|
|
- ✅ 数据一致性强
|
|||
|
|
- ✅ 查询方便
|
|||
|
|
- ✅ 自动更新
|
|||
|
|
- ✅ 无需维护冗余
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 当前问题
|
|||
|
|
|
|||
|
|
### 问题1: users.referred_by 不准确
|
|||
|
|
|
|||
|
|
**场景**:绑定过期后,`users.referred_by` 仍然有值
|
|||
|
|
|
|||
|
|
**影响**:
|
|||
|
|
```typescript
|
|||
|
|
// 错误的查询
|
|||
|
|
SELECT * FROM users WHERE referred_by = ?
|
|||
|
|
// 会查到已过期的用户
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**解决方案**:
|
|||
|
|
1. 停用 `users.referred_by`,只用 `referral_bindings`
|
|||
|
|
2. 或者在过期时清空 `users.referred_by`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 问题2: 旧代码依赖 users.referred_by
|
|||
|
|
|
|||
|
|
**位置**:`/api/referral/bind` 的 GET 接口
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 旧代码
|
|||
|
|
SELECT * FROM users WHERE referred_by = ?
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**应该改为**:
|
|||
|
|
```typescript
|
|||
|
|
// 新代码
|
|||
|
|
SELECT u.* FROM users u
|
|||
|
|
JOIN referral_bindings rb ON u.id = rb.referee_id
|
|||
|
|
WHERE rb.referrer_id = ?
|
|||
|
|
AND rb.status = 'active'
|
|||
|
|
AND rb.expiry_date > NOW()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 推荐方案
|
|||
|
|
|
|||
|
|
### 方案A: 渐进式优化(推荐)
|
|||
|
|
|
|||
|
|
**步骤1: 停用 users.referred_by**
|
|||
|
|
- 不再更新 `users.referred_by`
|
|||
|
|
- 所有查询改用 `referral_bindings`
|
|||
|
|
|
|||
|
|
**步骤2: 优化索引**
|
|||
|
|
- 确保 `referral_bindings` 有合适的索引
|
|||
|
|
- `idx_referee_status` ✅ 已有
|
|||
|
|
- `idx_referrer_status` ✅ 已有
|
|||
|
|
|
|||
|
|
**步骤3: 创建辅助函数**
|
|||
|
|
```typescript
|
|||
|
|
// 获取用户的当前推荐人
|
|||
|
|
async function getCurrentReferrer(userId: string) {
|
|||
|
|
const bindings = await query(`
|
|||
|
|
SELECT referrer_id, expiry_date, purchase_count
|
|||
|
|
FROM referral_bindings
|
|||
|
|
WHERE referee_id = ?
|
|||
|
|
AND status = 'active'
|
|||
|
|
AND expiry_date > NOW()
|
|||
|
|
ORDER BY binding_date DESC
|
|||
|
|
LIMIT 1
|
|||
|
|
`, [userId])
|
|||
|
|
|
|||
|
|
return bindings[0]?.referrer_id || null
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**优势**:
|
|||
|
|
- ✅ 数据一致性强
|
|||
|
|
- ✅ 无需维护冗余
|
|||
|
|
- ✅ 性能优秀(有索引)
|
|||
|
|
- ✅ 维护成本低
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 方案B: 保留 users.referred_by(不推荐)
|
|||
|
|
|
|||
|
|
如果一定要保留,需要确保同步:
|
|||
|
|
|
|||
|
|
**同步点**:
|
|||
|
|
1. ✅ 新绑定时(已实现)
|
|||
|
|
2. ✅ 切换推荐人时(已实现)
|
|||
|
|
3. ❌ 绑定过期时(需要添加)
|
|||
|
|
4. ❌ 绑定取消时(需要添加)
|
|||
|
|
|
|||
|
|
**实现**:
|
|||
|
|
```typescript
|
|||
|
|
// 在自动解绑时
|
|||
|
|
UPDATE users SET referred_by = NULL
|
|||
|
|
WHERE id IN (
|
|||
|
|
SELECT referee_id FROM referral_bindings
|
|||
|
|
WHERE status = 'expired'
|
|||
|
|
)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**劣势**:
|
|||
|
|
- ❌ 维护成本高
|
|||
|
|
- ❌ 容易出错
|
|||
|
|
- ❌ 收益不大
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 性能对比
|
|||
|
|
|
|||
|
|
### 查询1: 获取用户的推荐人
|
|||
|
|
|
|||
|
|
#### 使用 users.referred_by
|
|||
|
|
```sql
|
|||
|
|
SELECT referred_by FROM users WHERE id = ?
|
|||
|
|
```
|
|||
|
|
- 耗时:~0.01ms
|
|||
|
|
- 准确性:❌ 可能过期
|
|||
|
|
|
|||
|
|
#### 使用 referral_bindings
|
|||
|
|
```sql
|
|||
|
|
SELECT referrer_id FROM referral_bindings
|
|||
|
|
WHERE referee_id = ? AND status = 'active' AND expiry_date > NOW()
|
|||
|
|
LIMIT 1
|
|||
|
|
```
|
|||
|
|
- 耗时:~0.1ms(有索引)
|
|||
|
|
- 准确性:✅ 完全准确
|
|||
|
|
|
|||
|
|
**差异**:0.09ms(几乎可以忽略)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 查询2: 获取推荐人的下级列表
|
|||
|
|
|
|||
|
|
#### 使用 users.referred_by
|
|||
|
|
```sql
|
|||
|
|
SELECT * FROM users WHERE referred_by = ?
|
|||
|
|
```
|
|||
|
|
- 耗时:~1ms
|
|||
|
|
- 准确性:❌ 包含过期用户
|
|||
|
|
|
|||
|
|
#### 使用 referral_bindings
|
|||
|
|
```sql
|
|||
|
|
SELECT u.* FROM users u
|
|||
|
|
JOIN referral_bindings rb ON u.id = rb.referee_id
|
|||
|
|
WHERE rb.referrer_id = ?
|
|||
|
|
AND rb.status = 'active'
|
|||
|
|
AND rb.expiry_date > NOW()
|
|||
|
|
```
|
|||
|
|
- 耗时:~1.5ms(有索引)
|
|||
|
|
- 准确性:✅ 完全准确
|
|||
|
|
|
|||
|
|
**差异**:0.5ms(可接受)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✅ 结论与建议
|
|||
|
|
|
|||
|
|
### 推荐:方案A(只用 referral_bindings)
|
|||
|
|
|
|||
|
|
**理由**:
|
|||
|
|
1. ✅ **数据一致性**:单一数据源,避免不一致
|
|||
|
|
2. ✅ **逻辑清晰**:状态明确(active / expired / cancelled)
|
|||
|
|
3. ✅ **维护简单**:无需同步冗余字段
|
|||
|
|
4. ✅ **性能优秀**:有合适的索引,差异可忽略
|
|||
|
|
5. ✅ **功能完整**:支持过期、切换、购买次数等
|
|||
|
|
|
|||
|
|
### 不推荐:保留 users.referred_by
|
|||
|
|
|
|||
|
|
**理由**:
|
|||
|
|
1. ❌ 数据一致性差(容易出错)
|
|||
|
|
2. ❌ 维护成本高(多处同步)
|
|||
|
|
3. ❌ 性能提升微乎其微(0.09ms)
|
|||
|
|
4. ❌ 功能受限(无法判断是否过期)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔧 优化建议
|
|||
|
|
|
|||
|
|
### 短期优化(立即执行)
|
|||
|
|
|
|||
|
|
1. **停用 users.referred_by 的写入**
|
|||
|
|
- 不再更新这个字段
|
|||
|
|
- 保留字段(避免破坏性变更)
|
|||
|
|
|
|||
|
|
2. **修改旧查询**
|
|||
|
|
- 找到所有使用 `users.referred_by` 的查询
|
|||
|
|
- 改用 `referral_bindings`
|
|||
|
|
|
|||
|
|
3. **添加辅助函数**
|
|||
|
|
- 封装常用查询
|
|||
|
|
- 简化代码
|
|||
|
|
|
|||
|
|
### 中期优化(1-2周内)
|
|||
|
|
|
|||
|
|
1. **性能监控**
|
|||
|
|
- 监控查询性能
|
|||
|
|
- 确保没有性能问题
|
|||
|
|
|
|||
|
|
2. **数据清理**
|
|||
|
|
- 可选:清空 `users.referred_by`
|
|||
|
|
- 避免误用
|
|||
|
|
|
|||
|
|
### 长期优化(可选)
|
|||
|
|
|
|||
|
|
1. **删除冗余字段**
|
|||
|
|
- 如果确认不再使用
|
|||
|
|
- 彻底删除 `users.referred_by`
|
|||
|
|
|
|||
|
|
2. **创建视图或缓存**
|
|||
|
|
- 如果有特殊性能需求
|
|||
|
|
- 考虑 Redis 缓存
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📝 具体修改建议
|
|||
|
|
|
|||
|
|
### 1. 停止更新 users.referred_by
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// app/api/referral/bind/route.ts
|
|||
|
|
|
|||
|
|
// 删除或注释掉这行
|
|||
|
|
// await query('UPDATE users SET referred_by = ? WHERE id = ?', [referrer.id, user.id])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 修改旧查询
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// 旧代码
|
|||
|
|
const users = await query('SELECT * FROM users WHERE referred_by = ?', [userId])
|
|||
|
|
|
|||
|
|
// 新代码
|
|||
|
|
const users = await query(`
|
|||
|
|
SELECT u.* FROM users u
|
|||
|
|
JOIN referral_bindings rb ON u.id = rb.referee_id
|
|||
|
|
WHERE rb.referrer_id = ?
|
|||
|
|
AND rb.status = 'active'
|
|||
|
|
AND rb.expiry_date > NOW()
|
|||
|
|
`, [userId])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 添加辅助函数
|
|||
|
|
|
|||
|
|
```typescript
|
|||
|
|
// lib/referral-helpers.ts
|
|||
|
|
|
|||
|
|
export async function getCurrentReferrer(userId: string) {
|
|||
|
|
const bindings = await query(`
|
|||
|
|
SELECT referrer_id, expiry_date, purchase_count, total_commission
|
|||
|
|
FROM referral_bindings
|
|||
|
|
WHERE referee_id = ?
|
|||
|
|
AND status = 'active'
|
|||
|
|
AND expiry_date > NOW()
|
|||
|
|
ORDER BY binding_date DESC
|
|||
|
|
LIMIT 1
|
|||
|
|
`, [userId])
|
|||
|
|
|
|||
|
|
return bindings[0] || null
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export async function getActiveReferrals(referrerId: string) {
|
|||
|
|
return await query(`
|
|||
|
|
SELECT
|
|||
|
|
u.id, u.nickname, u.avatar,
|
|||
|
|
rb.binding_date, rb.expiry_date, rb.purchase_count, rb.total_commission
|
|||
|
|
FROM referral_bindings rb
|
|||
|
|
JOIN users u ON rb.referee_id = u.id
|
|||
|
|
WHERE rb.referrer_id = ?
|
|||
|
|
AND rb.status = 'active'
|
|||
|
|
AND rb.expiry_date > NOW()
|
|||
|
|
ORDER BY rb.binding_date DESC
|
|||
|
|
`, [referrerId])
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**总结:建议停用 users.referred_by,只使用 referral_bindings 表,性能差异微乎其微,但数据一致性大幅提升!**
|