新增数据库相关语句脚本
This commit is contained in:
@@ -1453,3 +1453,81 @@ echo "Done"
|
||||
| 清空 api/logs 今天日志 | `ssh root@47.98.203.17 "docker exec youle-api truncate -s 0 /var/www/html/logs/$(Get-Date -Format 'yyyy-MM-dd').log"` |
|
||||
| 清空同步调试日志 | `ssh root@47.98.203.17 "docker exec youle-dlweb truncate -s 0 /var/www/html/api/ext/debug/synchronize/$(Get-Date -Format 'yyyy-MM-dd').log"` |
|
||||
| 删除全部调试日志 | `ssh root@47.98.203.17 "docker exec youle-dlweb sh -c 'rm -f /var/www/html/api/ext/debug/synchronize/*.log /var/www/html/api/ext/debug/SynchronizeReportData/*.log /var/www/html/api/ext/debug/autotask/*.log'"` |
|
||||
|
||||
---
|
||||
|
||||
## 数据库远程管理(Navicat SSH 隧道)
|
||||
|
||||
> RDS 白名单仅开放服务器 `47.98.203.17`,任何设备需通过 SSH 隧道访问数据库,无需开放公网 IP,安全可控。
|
||||
|
||||
### 原理
|
||||
|
||||
```
|
||||
本机 Navicat ──SSH加密隧道──▶ 47.98.203.17 ──内网──▶ RDS MySQL
|
||||
```
|
||||
|
||||
### Navicat 连接配置(以 agent_db 为例)
|
||||
|
||||
#### 第一步:SSH 标签页
|
||||
|
||||
| 字段 | 值 |
|
||||
|------|----|
|
||||
| 使用 SSH 通道 | ✅ 勾选 |
|
||||
| 主机 | `47.98.203.17` |
|
||||
| 端口 | `22` |
|
||||
| 用户名 | `root` |
|
||||
| 验证方法 | **公钥** |
|
||||
| 私钥文件 | `C:\Users\{你的用户名}\.ssh\id_ed25519` |
|
||||
|
||||
> **注意**:当前服务器已授权的密钥为 `id_ed25519`(标识 `youle-deploy`),选错密钥会导致认证失败。
|
||||
|
||||
#### 第二步:常规标签页
|
||||
|
||||
| 字段 | 值 |
|
||||
|------|----|
|
||||
| 主机名/IP | `rm-bp1btyuwq77591x0jpo.mysql.rds.aliyuncs.com` |
|
||||
| 端口 | `3306` |
|
||||
| 用户名 | `games` |
|
||||
| 密码 | `Games0791!!` |
|
||||
| 数据库 | `agent_db`(可留空后再选) |
|
||||
|
||||
> ⚠️ **常见错误(2013 错误)**:常规标签的主机名填了 `127.0.0.1` 或 `localhost`,会连接到服务器本机而非 RDS,导致握手失败。必须填 RDS 完整域名。
|
||||
|
||||
#### 数据库与 RDS 实例对应关系
|
||||
|
||||
| 数据库 | RDS 主机 |
|
||||
|--------|---------|
|
||||
| `agent_db`、`agent_db_temp`、`game_field`、`youlehudong` | `rm-bp1btyuwq77591x0jpo.mysql.rds.aliyuncs.com` |
|
||||
| `game_db`、`grade_db` | `rm-bp1749tfxu2rpq670lo.mysql.rds.aliyuncs.com` |
|
||||
|
||||
### 新设备接入
|
||||
|
||||
在新设备上执行以下步骤:
|
||||
|
||||
```powershell
|
||||
# 1. 生成密钥对(如没有)
|
||||
ssh-keygen -t ed25519 -C "设备标识备注"
|
||||
|
||||
# 2. 查看公钥内容
|
||||
Get-Content "$env:USERPROFILE\.ssh\id_ed25519.pub"
|
||||
```
|
||||
|
||||
将公钥内容追加到服务器:
|
||||
|
||||
```bash
|
||||
ssh root@47.98.203.17 "echo 'ssh-ed25519 AAAA...你的公钥内容...' >> ~/.ssh/authorized_keys"
|
||||
```
|
||||
|
||||
之后 Navicat SSH 标签填写该设备的私钥路径即可。
|
||||
|
||||
### 命令行手动隧道(可选)
|
||||
|
||||
如需在命令行工具(如 mysql CLI)中使用,可手动建立隧道:
|
||||
|
||||
```bash
|
||||
# 建立隧道(保持此终端运行,另开终端连接)
|
||||
ssh -L 3307:rm-bp1btyuwq77591x0jpo.mysql.rds.aliyuncs.com:3306 root@47.98.203.17 -N
|
||||
|
||||
# 另开终端,连接本地转发端口
|
||||
mysql -h 127.0.0.1 -P 3307 -u games -p agent_db
|
||||
```
|
||||
|
||||
21
codes/games/sql/export/export_summary.bat
Normal file
21
codes/games/sql/export/export_summary.bat
Normal file
@@ -0,0 +1,21 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
cd /d "%~dp0"
|
||||
|
||||
where node >nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo [错误] 未找到 Node.js,请先安装 Node.js
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if not exist "node_modules" (
|
||||
echo [初始化] 首次运行,正在安装依赖...
|
||||
npm install
|
||||
echo.
|
||||
)
|
||||
|
||||
node export_summary.js %*
|
||||
|
||||
echo.
|
||||
pause
|
||||
260
codes/games/sql/export/export_summary.js
Normal file
260
codes/games/sql/export/export_summary.js
Normal file
@@ -0,0 +1,260 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* export_summary.js
|
||||
* 通过 SSH 隧道连接 RDS,导出转卡汇总报表为 Excel
|
||||
*
|
||||
* 用法:
|
||||
* node export_summary.js # 交互式输入年月
|
||||
* node export_summary.js -y 2026 -m 3 # 直接指定年月
|
||||
*
|
||||
* 依赖: npm install mysql2 exceljs tunnel-ssh
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const readline = require("readline");
|
||||
const { createTunnel } = require("tunnel-ssh");
|
||||
const mysql = require("mysql2/promise");
|
||||
const ExcelJS = require("exceljs");
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// SSH 配置(跳板机)
|
||||
// ─────────────────────────────────────────────
|
||||
const SSH_CONFIG = {
|
||||
host: "47.98.203.17",
|
||||
port: 22,
|
||||
username: "root",
|
||||
privateKey: fs.readFileSync(
|
||||
path.join(process.env.USERPROFILE || process.env.HOME, ".ssh", "id_ed25519")
|
||||
),
|
||||
};
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// 数据库配置(RDS,通过 SSH 隧道访问)
|
||||
// ─────────────────────────────────────────────
|
||||
const DB_HOST = "rm-bp1btyuwq77591x0jpo.mysql.rds.aliyuncs.com";
|
||||
const DB_PORT = 3306;
|
||||
const DB_CONFIG = {
|
||||
host: "127.0.0.1",
|
||||
port: 13306, // 本地隧道转发端口
|
||||
user: "games",
|
||||
password: "Games0791!!",
|
||||
database: "agent_db",
|
||||
charset: "utf8mb4",
|
||||
connectTimeout: 15000,
|
||||
};
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// 默认业务参数
|
||||
// ─────────────────────────────────────────────
|
||||
const DEFAULT_FROM_SALES = 10437216;
|
||||
const DEFAULT_AGENT_ID = "veRa0qrBf0df2K1G4de2tgfmVxB2jxpv";
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// Excel 样式
|
||||
// ─────────────────────────────────────────────
|
||||
const COLOR_HEADER = "2E6DA4";
|
||||
const COLOR_TOTAL_ROW = "FFF2CC";
|
||||
const COLOR_ALT_ROW = "EBF3FB";
|
||||
|
||||
function headerStyle() {
|
||||
return {
|
||||
font: { bold: true, color: { argb: "FFFFFFFF" }, size: 11 },
|
||||
fill: { type: "pattern", pattern: "solid", fgColor: { argb: "FF" + COLOR_HEADER } },
|
||||
alignment: { horizontal: "center", vertical: "middle", wrapText: true },
|
||||
border: thinBorder(),
|
||||
};
|
||||
}
|
||||
|
||||
function thinBorder() {
|
||||
const s = { style: "thin", color: { argb: "FFBFBFBF" } };
|
||||
return { left: s, right: s, top: s, bottom: s };
|
||||
}
|
||||
|
||||
function applyStyle(cell, style) {
|
||||
Object.assign(cell, style);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// 汇总 SQL(不含 ROLLUP,合计行由 JS 端计算)
|
||||
// ─────────────────────────────────────────────
|
||||
const SQL_SUMMARY = `
|
||||
SELECT
|
||||
t.satr_salesid AS agentId,
|
||||
MAX(su.saus_nickname) AS agentName,
|
||||
COUNT(t.idx) AS transferCount,
|
||||
SUM(t.satr_amount) AS transferTotal
|
||||
FROM
|
||||
sales_transferbill t
|
||||
LEFT JOIN sales_user su
|
||||
ON t.satr_agentid = su.saus_agentid
|
||||
AND t.channel_id = su.saus_channelid
|
||||
AND t.satr_salesid = su.saus_salesid
|
||||
WHERE
|
||||
t.satr_agentid = ?
|
||||
AND t.from_sales = ?
|
||||
AND YEAR(t.satr_transfertime) = ?
|
||||
AND MONTH(t.satr_transfertime) = ?
|
||||
GROUP BY t.satr_salesid
|
||||
ORDER BY SUM(t.satr_amount) DESC
|
||||
`;
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// 建立 SSH 隧道(tunnel-ssh v5)
|
||||
// ─────────────────────────────────────────────
|
||||
async function openTunnel() {
|
||||
const tunnelOptions = { autoClose: true };
|
||||
const serverOptions = { port: DB_CONFIG.port };
|
||||
const sshOptions = SSH_CONFIG;
|
||||
const forwardOptions = {
|
||||
srcAddr: "127.0.0.1",
|
||||
srcPort: DB_CONFIG.port,
|
||||
dstAddr: DB_HOST,
|
||||
dstPort: DB_PORT,
|
||||
};
|
||||
const [server] = await createTunnel(tunnelOptions, serverOptions, sshOptions, forwardOptions);
|
||||
return server;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// 写 Excel
|
||||
// ─────────────────────────────────────────────
|
||||
async function writeExcel(rows, year, month, fromSales, outputPath) {
|
||||
const wb = new ExcelJS.Workbook();
|
||||
const ws = wb.addWorksheet("转卡汇总");
|
||||
ws.properties.tabColor = { argb: "FF" + COLOR_HEADER };
|
||||
ws.views = [{ state: "frozen", ySplit: 1 }];
|
||||
|
||||
// 列定义
|
||||
const columns = [
|
||||
{ header: "代理ID", key: "agentId", width: 14 },
|
||||
{ header: "代理昵称", key: "agentName", width: 20 },
|
||||
{ header: "转卡次数", key: "transferCount", width: 12 },
|
||||
{ header: "转卡总量", key: "transferTotal", width: 12 },
|
||||
];
|
||||
ws.columns = columns;
|
||||
|
||||
// 表头样式
|
||||
const hs = headerStyle();
|
||||
ws.getRow(1).height = 22;
|
||||
ws.getRow(1).eachCell(cell => applyStyle(cell, hs));
|
||||
|
||||
// 数据行
|
||||
let totalCount = 0, totalAmount = 0;
|
||||
rows.forEach((row, idx) => {
|
||||
const r = ws.addRow({
|
||||
agentId: row.agentId,
|
||||
agentName: row.agentName || "—",
|
||||
transferCount: Number(row.transferCount),
|
||||
transferTotal: Number(row.transferTotal),
|
||||
});
|
||||
r.height = 20;
|
||||
const isAlt = (idx % 2 === 1);
|
||||
r.eachCell(cell => {
|
||||
cell.border = thinBorder();
|
||||
cell.alignment = { horizontal: "center", vertical: "middle" };
|
||||
if (isAlt) cell.fill = { type: "pattern", pattern: "solid", fgColor: { argb: "FF" + COLOR_ALT_ROW } };
|
||||
});
|
||||
totalCount += Number(row.transferCount);
|
||||
totalAmount += Number(row.transferTotal);
|
||||
});
|
||||
|
||||
// 合计行
|
||||
const totalRow = ws.addRow({
|
||||
agentId: "★ 合计",
|
||||
agentName: "—",
|
||||
transferCount: totalCount,
|
||||
transferTotal: totalAmount,
|
||||
});
|
||||
totalRow.height = 22;
|
||||
totalRow.eachCell(cell => {
|
||||
cell.border = thinBorder();
|
||||
cell.font = { bold: true, size: 11 };
|
||||
cell.alignment = { horizontal: "center", vertical: "middle" };
|
||||
cell.fill = { type: "pattern", pattern: "solid", fgColor: { argb: "FF" + COLOR_TOTAL_ROW } };
|
||||
});
|
||||
|
||||
await wb.xlsx.writeFile(outputPath);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// 交互式询问
|
||||
// ─────────────────────────────────────────────
|
||||
async function prompt(question) {
|
||||
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
return new Promise(resolve => rl.question(question, ans => { rl.close(); resolve(ans.trim()); }));
|
||||
}
|
||||
|
||||
async function getParams() {
|
||||
const args = process.argv.slice(2);
|
||||
const get = (flag) => { const i = args.indexOf(flag); return i !== -1 ? args[i + 1] : null; };
|
||||
const now = new Date();
|
||||
|
||||
let year = get("-y") ? parseInt(get("-y")) : null;
|
||||
let month = get("-m") ? parseInt(get("-m")) : null;
|
||||
let fromSales = get("-f") ? parseInt(get("-f")) : DEFAULT_FROM_SALES;
|
||||
let agentId = get("-a") ? get("-a") : DEFAULT_AGENT_ID;
|
||||
|
||||
if (!year) {
|
||||
const raw = await prompt(`请输入年份(直接回车使用 ${now.getFullYear()}): `);
|
||||
year = raw ? parseInt(raw) : now.getFullYear();
|
||||
}
|
||||
if (!month) {
|
||||
const raw = await prompt(`请输入月份 1-12(直接回车使用 ${now.getMonth() + 1}): `);
|
||||
month = raw ? parseInt(raw) : now.getMonth() + 1;
|
||||
}
|
||||
if (month < 1 || month > 12) { console.error("[错误] 月份必须在 1-12 之间"); process.exit(1); }
|
||||
|
||||
return { year, month, fromSales, agentId };
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────
|
||||
// 主流程
|
||||
// ─────────────────────────────────────────────
|
||||
async function main() {
|
||||
const { year, month, fromSales, agentId } = await getParams();
|
||||
|
||||
const outputDir = path.join(__dirname, "output");
|
||||
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
|
||||
const outputFile = path.join(outputDir, `转卡汇总_${year}${String(month).padStart(2, "0")}_${fromSales}.xlsx`);
|
||||
|
||||
console.log("=".repeat(55));
|
||||
console.log(` 导出参数: ${year}年${String(month).padStart(2, "0")}月`);
|
||||
console.log(` 发卡代理: ${fromSales}`);
|
||||
console.log(` 代理商ID: ${agentId}`);
|
||||
console.log(` 输出文件: ${outputFile}`);
|
||||
console.log("=".repeat(55));
|
||||
|
||||
console.log("\n[SSH] 正在建立隧道 47.98.203.17 → RDS ...");
|
||||
const tunnel = await openTunnel();
|
||||
console.log("[SSH] 隧道建立成功");
|
||||
|
||||
let conn;
|
||||
try {
|
||||
console.log("[数据库] 正在连接 ...");
|
||||
conn = await mysql.createConnection(DB_CONFIG);
|
||||
console.log("[数据库] 连接成功");
|
||||
|
||||
console.log(`[查询] 执行汇总查询 (${year}年${String(month).padStart(2, "0")}月) ...`);
|
||||
const [rows] = await conn.execute(SQL_SUMMARY, [agentId, fromSales, year, month]);
|
||||
console.log(` 共 ${rows.length} 条代理记录`);
|
||||
|
||||
if (rows.length === 0) {
|
||||
console.log("[提示] 查询结果为空,未生成文件");
|
||||
} else {
|
||||
await writeExcel(rows, year, month, fromSales, outputFile);
|
||||
console.log(`\n[完成] 文件已保存: ${outputFile}`);
|
||||
}
|
||||
} finally {
|
||||
if (conn) await conn.end();
|
||||
tunnel.close();
|
||||
console.log("[SSH] 隧道已关闭");
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error("\n[错误]", err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
1118
codes/games/sql/export/package-lock.json
generated
Normal file
1118
codes/games/sql/export/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
codes/games/sql/export/package.json
Normal file
14
codes/games/sql/export/package.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "youle-sql-export",
|
||||
"version": "1.0.0",
|
||||
"description": "转卡报表导出工具",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"export": "node export_summary.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"exceljs": "^4.4.0",
|
||||
"mysql2": "^3.22.0",
|
||||
"tunnel-ssh": "^5.2.0"
|
||||
}
|
||||
}
|
||||
49
codes/games/sql/game/scripts/room_players.sql
Normal file
49
codes/games/sql/game/scripts/room_players.sql
Normal file
@@ -0,0 +1,49 @@
|
||||
-- ============================================================
|
||||
-- 脚本名称: room_players.sql
|
||||
-- 功 能: 查询指定房间号的所有历史对局及每局玩家信息
|
||||
-- 数据库 : grade_db + game_db(跨库,同一RDS实例)
|
||||
-- RDS: rm-bp1749tfxu2rpq670lo
|
||||
-- 说明 :
|
||||
-- 同一房间号可能在不同时间出现多次,结果按开房时间分组。
|
||||
-- 输出按「开房时间 DESC → 得分 DESC」排序,
|
||||
-- 相同开房时间的行即为同一场对局,可在结果中直接区分。
|
||||
-- ============================================================
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【参数设置】 ← 修改这里
|
||||
-- ============================================================
|
||||
SET @p_agentid = 'veRa0qrBf0df2K1G4de2tgfmVxB2jxpv'; -- 代理商ID
|
||||
SET @p_roomcode = 0; -- 房间号(plgr_roomcode)
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【查询】指定房间号的所有历史对局玩家明细
|
||||
-- 结果按开房时间倒序排列,同一开房时间为同一场对局
|
||||
-- ============================================================
|
||||
SELECT
|
||||
DATE_FORMAT(pg.plgr_createtime, '%Y-%m-%d %H:%i:%s') AS '创建时间',
|
||||
DATE_FORMAT(pg.plgr_overtime, '%Y-%m-%d %H:%i:%s') AS '结束时间',
|
||||
pg.plgr_roomcode AS '房间号',
|
||||
pg.plgr_playerid AS '玩家ID',
|
||||
p.play_nickname AS '玩家昵称',
|
||||
pg.plgr_score AS '得分',
|
||||
pg.plgr_winner AS '是否大赢家(1=是)',
|
||||
pg.plgr_deductcard AS '扣除房卡',
|
||||
DATE_FORMAT(pg.plgr_makewartime, '%Y-%m-%d %H:%i:%s') AS '开战时间',
|
||||
pg.plgr_roomtype AS '房间类型',
|
||||
pg.plgr_gameid AS '游戏ID',
|
||||
g.game_name AS '游戏名称'
|
||||
FROM
|
||||
grade_db.player_grade pg
|
||||
LEFT JOIN game_db.player p
|
||||
ON pg.plgr_agentid = p.play_agentid
|
||||
AND pg.plgr_playerid = p.play_playerid
|
||||
LEFT JOIN game_db.game g
|
||||
ON pg.plgr_gameid = g.game_gameid
|
||||
WHERE
|
||||
pg.plgr_agentid = @p_agentid
|
||||
AND pg.plgr_roomcode = @p_roomcode
|
||||
ORDER BY
|
||||
pg.plgr_createtime DESC,
|
||||
pg.plgr_score DESC;
|
||||
46
codes/games/sql/game/scripts/transfer_detail.sql
Normal file
46
codes/games/sql/game/scripts/transfer_detail.sql
Normal file
@@ -0,0 +1,46 @@
|
||||
-- ============================================================
|
||||
-- 脚本名称: transfer_detail.sql
|
||||
-- 功 能: 指定年月的转卡明细流水(每笔转卡一行)
|
||||
-- 数据库 : agent_db
|
||||
-- 用 法:
|
||||
-- 1. 修改下方【参数设置】中的变量值
|
||||
-- 2. 在 Navicat 中执行全部脚本
|
||||
-- 3. 结果集右键 → Export → Excel 可导出表格
|
||||
-- ============================================================
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【参数设置】 ← 修改这里
|
||||
-- ============================================================
|
||||
SET @p_year = 2026; -- 年份
|
||||
SET @p_month = 3; -- 月份(1-12)
|
||||
SET @p_from_sales = 10437216; -- 发卡来源代理ID(上级代理)
|
||||
SET @p_agent_id = 'veRa0qrBf0df2K1G4de2tgfmVxB2jxpv'; -- 代理商ID
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【明细报表】每一笔转卡流水记录,按转卡时间升序排列
|
||||
-- ============================================================
|
||||
SELECT
|
||||
t.from_sales AS '发卡代理ID',
|
||||
su_from.saus_nickname AS '发卡代理昵称',
|
||||
t.satr_salesid AS '接收代理ID',
|
||||
su_to.saus_nickname AS '接收代理昵称',
|
||||
t.satr_amount AS '转卡数量',
|
||||
DATE_FORMAT(t.satr_transfertime, '%Y-%m-%d %H:%i:%s') AS '转卡时间'
|
||||
FROM
|
||||
sales_transferbill t
|
||||
LEFT JOIN sales_user su_to
|
||||
ON t.satr_agentid = su_to.saus_agentid
|
||||
AND t.channel_id = su_to.saus_channelid
|
||||
AND t.satr_salesid = su_to.saus_salesid
|
||||
LEFT JOIN sales_user su_from
|
||||
ON t.satr_agentid = su_from.saus_agentid
|
||||
AND t.from_sales = su_from.saus_salesid
|
||||
WHERE
|
||||
t.satr_agentid = @p_agent_id
|
||||
AND t.from_sales = @p_from_sales
|
||||
AND YEAR(t.satr_transfertime) = @p_year
|
||||
AND MONTH(t.satr_transfertime) = @p_month
|
||||
ORDER BY
|
||||
t.satr_transfertime ASC;
|
||||
49
codes/games/sql/game/scripts/transfer_summary.sql
Normal file
49
codes/games/sql/game/scripts/transfer_summary.sql
Normal file
@@ -0,0 +1,49 @@
|
||||
-- ============================================================
|
||||
-- 脚本名称: transfer_summary.sql
|
||||
-- 功 能: 指定年月的转卡汇总报表(按下级代理分组,含合计行)
|
||||
-- 数据库 : agent_db
|
||||
-- 用 法:
|
||||
-- 1. 修改下方【参数设置】中的变量值
|
||||
-- 2. 在 Navicat 中执行全部脚本
|
||||
-- 3. 结果集右键 → Export → Excel 可导出表格
|
||||
-- ============================================================
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【参数设置】 ← 修改这里
|
||||
-- ============================================================
|
||||
SET @p_year = 2026; -- 年份
|
||||
SET @p_month = 3; -- 月份(1-12)
|
||||
SET @p_from_sales = 10437216; -- 发卡来源代理ID(上级代理)
|
||||
SET @p_agent_id = 'veRa0qrBf0df2K1G4de2tgfmVxB2jxpv'; -- 代理商ID
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【汇总报表】按下级代理分组,最后一行为转卡总计
|
||||
-- ============================================================
|
||||
SELECT
|
||||
IF(
|
||||
GROUPING(t.satr_salesid),
|
||||
'★ 合计',
|
||||
CAST(t.satr_salesid AS CHAR)
|
||||
) AS '代理ID',
|
||||
IF(
|
||||
GROUPING(t.satr_salesid),
|
||||
'—',
|
||||
MAX(su.saus_nickname)
|
||||
) AS '代理昵称',
|
||||
COUNT(t.idx) AS '转卡次数',
|
||||
SUM(t.satr_amount) AS '转卡总量'
|
||||
FROM
|
||||
sales_transferbill t
|
||||
LEFT JOIN sales_user su
|
||||
ON t.satr_agentid = su.saus_agentid
|
||||
AND t.channel_id = su.saus_channelid
|
||||
AND t.satr_salesid = su.saus_salesid
|
||||
WHERE
|
||||
t.satr_agentid = @p_agent_id
|
||||
AND t.from_sales = @p_from_sales
|
||||
AND YEAR(t.satr_transfertime) = @p_year
|
||||
AND MONTH(t.satr_transfertime) = @p_month
|
||||
GROUP BY
|
||||
t.satr_salesid WITH ROLLUP;
|
||||
45
codes/games/sql/game/scripts/update_player_roomcard.sql
Normal file
45
codes/games/sql/game/scripts/update_player_roomcard.sql
Normal file
@@ -0,0 +1,45 @@
|
||||
-- ============================================================
|
||||
-- 脚本名称: update_player_roomcard.sql
|
||||
-- 功 能: 更新指定玩家的房卡数量
|
||||
-- 数据库 : game_db(RDS: rm-bp1749tfxu2rpq670lo)
|
||||
-- 用 法:
|
||||
-- 1. 修改下方【参数设置】中的变量值
|
||||
-- 2. 先执行【查询确认】,核对目标玩家信息无误
|
||||
-- 3. 确认无误后再执行【执行更新】
|
||||
-- ============================================================
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【参数设置】 ← 修改这里
|
||||
-- ============================================================
|
||||
SET @p_agentid = 'veRa0qrBf0df2K1G4de2tgfmVxB2jxpv'; -- 代理商ID
|
||||
SET @p_playerid = 0; -- 玩家ID(play_playerid)
|
||||
SET @p_roomcard = 0; -- 要设置的房卡数量
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【第一步:查询确认】执行后确认玩家信息正确再继续
|
||||
-- ============================================================
|
||||
SELECT
|
||||
play_agentid AS '代理商ID',
|
||||
play_playerid AS '玩家ID',
|
||||
play_nickname AS '玩家昵称',
|
||||
play_roomcard AS '当前房卡数',
|
||||
@p_roomcard AS '更新后房卡数'
|
||||
FROM
|
||||
player
|
||||
WHERE
|
||||
play_agentid = @p_agentid
|
||||
AND play_playerid = @p_playerid;
|
||||
|
||||
|
||||
-- ============================================================
|
||||
-- 【第二步:执行更新】确认玩家信息无误后执行此段
|
||||
-- ============================================================
|
||||
UPDATE player
|
||||
SET play_roomcard = @p_roomcard
|
||||
WHERE play_agentid = @p_agentid
|
||||
AND play_playerid = @p_playerid;
|
||||
|
||||
-- 输出影响行数(1 = 更新成功,0 = 未找到对应玩家)
|
||||
SELECT ROW_COUNT() AS '影响行数(1=成功,0=未找到玩家)';
|
||||
Reference in New Issue
Block a user