ai_member_xiaoxi/scripts/learning_progress_30days.py
2026-05-28 08:00:01 +08:00

121 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""查询2026年3月后未退费订单激活课程在下单30天内的学习进度分布"""
import psycopg2
import os
import sys
# 数据库连接
conn = psycopg2.connect(
host="bj-postgres-16pob4sg.sql.tencentcdb.com",
port=28591,
user="ai_member",
password="LdfjdjL83h3h3^$&**YGG*",
dbname="vala_bi"
)
cur = conn.cursor()
sql = """WITH orders AS (
SELECT o.id, o.out_trade_no, o.account_id, o.pay_success_date
FROM bi_vala_order o
JOIN bi_vala_app_account a ON o.account_id = a.id
WHERE o.pay_success_date >= '2026-03-01'
AND o.order_status != 4
AND o.pay_success_date IS NOT NULL
AND a.status = 1
),
tickets AS (
SELECT o.out_trade_no, o.account_id, o.pay_success_date,
t.character_id, t.season_package_level
FROM orders o
JOIN bi_vala_seasonal_ticket t ON o.out_trade_no = t.out_trade_no
WHERE t.status = 1
AND t.deleted_at IS NULL
AND t.season_package_level IN ('A1', 'A2')
),
all_chapter_records AS (
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_0 WHERE play_status = 1
UNION ALL
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_1 WHERE play_status = 1
UNION ALL
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_2 WHERE play_status = 1
UNION ALL
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_3 WHERE play_status = 1
UNION ALL
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_4 WHERE play_status = 1
UNION ALL
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_5 WHERE play_status = 1
UNION ALL
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_6 WHERE play_status = 1
UNION ALL
SELECT user_id, chapter_id, created_at FROM bi_user_chapter_play_record_7 WHERE play_status = 1
),
level_records AS (
SELECT pr.user_id, pr.chapter_id, pr.created_at, l.course_level
FROM all_chapter_records pr
JOIN bi_level_unit_lesson l ON pr.chapter_id = l.id
WHERE l.course_level IN ('L1', 'L2')
),
ticket_progress AS (
SELECT
t.out_trade_no,
t.account_id,
t.character_id,
t.season_package_level,
t.pay_success_date,
COUNT(DISTINCT lr.chapter_id) AS completed_lessons
FROM tickets t
LEFT JOIN level_records lr
ON t.character_id = lr.user_id
AND lr.course_level = CASE
WHEN t.season_package_level = 'A1' THEN 'L1'
WHEN t.season_package_level = 'A2' THEN 'L2'
END
AND lr.created_at >= t.pay_success_date
AND lr.created_at <= t.pay_success_date + INTERVAL '30 days'
GROUP BY t.out_trade_no, t.account_id, t.character_id, t.season_package_level, t.pay_success_date
)
SELECT
CASE WHEN season_package_level = 'A1' THEN 'L1' ELSE 'L2' END AS course_level,
completed_lessons,
COUNT(*) AS ticket_count,
ROUND(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER (PARTITION BY season_package_level), 1) AS pct
FROM ticket_progress
GROUP BY season_package_level, completed_lessons
ORDER BY season_package_level, completed_lessons;"""
print("正在查询...")
cur.execute(sql)
rows = cur.fetchall()
print(f"\n{'='*60}")
print("2026年3月后未退费订单 → 激活课程下单30天内学习进度分布")
print(f"{'='*60}")
l1_rows = [r for r in rows if r[0] == 'L1']
l2_rows = [r for r in rows if r[0] == 'L2']
for label, data in [('L1', l1_rows), ('L2', l2_rows)]:
print(f"\n--- {label} ---")
total = sum(r[2] for r in data)
print(f"总 ticket 数: {total}")
print(f"{'完课数':>8} | {'ticket数':>10} | {'占比':>8}")
print("-" * 35)
for r in data:
print(f"{r[1]:>8} | {r[2]:>10} | {r[3]:>7}%")
# 统计摘要
if data:
completed_values = []
for r in data:
completed_values.extend([r[1]] * r[2])
import statistics
avg = sum(completed_values) / len(completed_values) if completed_values else 0
median = statistics.median(completed_values) if completed_values else 0
zero_pct = sum(1 for v in completed_values if v == 0) / len(completed_values) * 100 if completed_values else 0
print(f"\n摘要: 平均={avg:.1f}节, 中位数={median:.0f}节, 0节课占比={zero_pct:.1f}%")
cur.close()
conn.close()
print("\n查询完成。")