fix(scripts): backfill_group_members 窗口函数化过 MySQL only_full_group_by(单库收敛)
max(timestamp)+裸 sender_name 的 GROUP BY 是 SQLite 方言行为,MySQL 8 默认 only_full_group_by 直接 1055 拒绝——2026-08-27 单库收敛(本地+调度器同连 Docker MySQL)时在 MySQL 上实跑触发。改 row_number() OVER 取每 (room_id, talker_id) 最新一行的 sender_name + count() OVER 计数:两库通用,且语义从 「碰巧取 max 行」变为严格最新一条。另 gitignore 补 *.db.retired (smoke.db 退役改名后 *.db 规则罩不住)。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ media/
|
||||
|
||||
# Local scratch DBs used for Alembic autogenerate (see migrations/env.py)
|
||||
*.db
|
||||
*.db.retired
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
.playwright-mcp/
|
||||
|
||||
@@ -26,13 +26,22 @@ from app.storage.repos import _upsert_one
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
|
||||
log = logging.getLogger("backfill_group_members")
|
||||
|
||||
# max(timestamp) 裸列:SQLite 保证 sender_name 取自 timestamp 最大的那行
|
||||
# row_number() 窗口取 timestamp 最新一行的 sender_name:MySQL 8 的
|
||||
# only_full_group_by 拒绝 SQLite 式「max()+裸列」(1055),窗口写法两库通用
|
||||
# 且语义严格(最新一条的昵称),不依赖方言碰巧行为
|
||||
SQL = sa_text("""
|
||||
SELECT room_id, talker_id, sender_name, max(timestamp) AS last_ts, count(*) AS msg_count
|
||||
FROM message
|
||||
WHERE channel = 'wechat' AND room_id IS NOT NULL AND room_id != ''
|
||||
AND talker_id IS NOT NULL AND talker_id != ''
|
||||
GROUP BY room_id, talker_id
|
||||
SELECT room_id, talker_id, sender_name, last_ts, msg_count
|
||||
FROM (
|
||||
SELECT room_id, talker_id, sender_name, timestamp AS last_ts,
|
||||
count(*) OVER (PARTITION BY room_id, talker_id) AS msg_count,
|
||||
row_number() OVER (
|
||||
PARTITION BY room_id, talker_id ORDER BY timestamp DESC
|
||||
) AS rn
|
||||
FROM message
|
||||
WHERE channel = 'wechat' AND room_id IS NOT NULL AND room_id != ''
|
||||
AND talker_id IS NOT NULL AND talker_id != ''
|
||||
) t
|
||||
WHERE rn = 1
|
||||
""")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user