ai_member_xiaoxi/scripts/query_chapter_play.sh

179 lines
6.0 KiB
Bash
Executable File
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.

#!/bin/bash
# 课时完成记录查询脚本
# 查询指定课时(chapter_id)的首次完成记录,包含角色信息、最近登录、课程耗时
# 数据库:线上 PostgreSQL (vala_bi)
# 输出xlsx 格式
# 用法bash scripts/query_chapter_play.sh
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
source "${SCRIPT_DIR}/../secrets.env"
DB_HOST="bj-postgres-16pob4sg.sql.tencentcdb.com"
DB_PORT="28591"
DB_USER="ai_member"
DB_NAME="vala_bi"
OUTPUT_DIR="${SCRIPT_DIR}/../output"
mkdir -p "$OUTPUT_DIR"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
CSV_TMP="${OUTPUT_DIR}/.chapter_play_${TIMESTAMP}.csv"
OUTPUT_FILE="${OUTPUT_DIR}/chapter_play_${TIMESTAMP}.xlsx"
SQL=$(cat <<'EOF'
WITH chapter_play AS (
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at) AS finish_date
FROM bi_user_chapter_play_record_0
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
UNION ALL
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at)
FROM bi_user_chapter_play_record_1
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
UNION ALL
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at)
FROM bi_user_chapter_play_record_2
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
UNION ALL
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at)
FROM bi_user_chapter_play_record_3
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
UNION ALL
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at)
FROM bi_user_chapter_play_record_4
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
UNION ALL
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at)
FROM bi_user_chapter_play_record_5
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
UNION ALL
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at)
FROM bi_user_chapter_play_record_6
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
UNION ALL
SELECT user_id, chapter_id, chapter_unique_id, date(updated_at)
FROM bi_user_chapter_play_record_7
WHERE chapter_id IN (55,56,57,58,59,343,344,345,346,348) AND play_status = 1
),
comp_time AS (
SELECT chapter_unique_id, SUM(interval_time) AS total_interval
FROM (
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_0
UNION ALL
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_1
UNION ALL
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_2
UNION ALL
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_3
UNION ALL
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_4
UNION ALL
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_5
UNION ALL
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_6
UNION ALL
SELECT chapter_unique_id, interval_time FROM bi_user_component_play_record_7
) t
GROUP BY chapter_unique_id
),
course_detail AS (
SELECT
cp.user_id,
cp.chapter_id,
FORMAT('%s-%s-%s-%s', l.course_level, l.course_season, l.course_unit, l.course_lesson) AS course_id,
cp.finish_date,
FORMAT('%s:%s',
FLOOR(ct.total_interval / 1000 / 60),
LPAD(CAST(MOD(ct.total_interval / 1000, 60) AS TEXT), 2, '0')
) AS finish_time
FROM (
SELECT user_id, chapter_id, chapter_unique_id, finish_date,
ROW_NUMBER() OVER (PARTITION BY user_id, chapter_id ORDER BY finish_date) AS rn
FROM chapter_play
) cp
LEFT JOIN bi_level_unit_lesson l ON cp.chapter_id = l.id
LEFT JOIN comp_time ct ON cp.chapter_unique_id = ct.chapter_unique_id
WHERE cp.rn = 1
)
SELECT
a.account_id AS "账号ID",
a.id AS "角色ID",
DATE(a.created_at) AS "注册日期",
DATE(TO_TIMESTAMP(b.latest_active_time)) AS "最近登录时间",
c.course_id AS "课程名称",
c.finish_date AS "课程完成时间",
c.finish_time AS "课程耗时"
FROM bi_vala_app_character a
LEFT JOIN user_detail_info b ON a.id = b.user_id
LEFT JOIN course_detail c ON a.id = c.user_id
WHERE a.status = 1
ORDER BY a.id, c.course_id;
EOF
)
echo "正在查询..."
PGPASSWORD="$PG_ONLINE_PASSWORD" psql \
-h "$DB_HOST" \
-p "$DB_PORT" \
-U "$DB_USER" \
-d "$DB_NAME" \
--csv \
-c "$SQL" \
> "$CSV_TMP"
ROW_COUNT=$(tail -n +2 "$CSV_TMP" | wc -l)
echo "查询完成,共 ${ROW_COUNT} 条记录,正在转换为 xlsx..."
python3 - "$CSV_TMP" "$OUTPUT_FILE" <<'PYEOF'
import csv, sys
from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill
csv_path, xlsx_path = sys.argv[1], sys.argv[2]
wb = Workbook()
ws = wb.active
ws.title = "课时完成记录"
# 读取 CSV
with open(csv_path, 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
ws.append(row)
# 表头样式
header_font = Font(bold=True, color="FFFFFF", size=11)
header_fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
header_align = Alignment(horizontal="center", vertical="center")
for cell in ws[1]:
cell.font = header_font
cell.fill = header_fill
cell.alignment = header_align
# 自动列宽
for col in ws.columns:
max_len = 0
col_letter = col[0].column_letter
for cell in col:
val = str(cell.value) if cell.value else ""
# 中文字符算 2 宽度
width = sum(2 if ord(c) > 127 else 1 for c in val)
if width > max_len:
max_len = width
ws.column_dimensions[col_letter].width = min(max_len + 3, 30)
# 冻结首行
ws.freeze_panes = "A2"
wb.save(xlsx_path)
print(f"xlsx 已保存: {xlsx_path}")
PYEOF
# 清理临时 CSV
rm -f "$CSV_TMP"
echo "完成!结果已保存至: ${OUTPUT_FILE}"