161 lines
7.5 KiB
Python
161 lines
7.5 KiB
Python
|
|
"""用 pymysql 直接跑改后的 SQL(与 routes/energy_stats.rs 中的语句逐字对应,
|
|||
|
|
唯一差别:Rust 用 `?` 占位符 + bind,这里把测试常量(org_id=1 / range=30)
|
|||
|
|
直接内联,以保持 SQL 文本与 Rust 生成的完全一致,并避开 pymysql 的 `%` 转义)。
|
|||
|
|
|
|||
|
|
只做只读 SELECT,不改任何数据。
|
|||
|
|
"""
|
|||
|
|
import pymysql
|
|||
|
|
|
|||
|
|
DB = dict(host="10.8.0.252", user="root", password="Hbhyg731024@", database="pms_dev")
|
|||
|
|
conn = pymysql.connect(**DB)
|
|||
|
|
cur = conn.cursor()
|
|||
|
|
|
|||
|
|
TODAY = "cr.start_time >= CURDATE() AND cr.start_time < CURDATE() + INTERVAL 1 DAY"
|
|||
|
|
THIS_MONTH = (
|
|||
|
|
"cr.start_time >= DATE_FORMAT(CURDATE(), '%Y-%m-01') "
|
|||
|
|
"AND cr.start_time < DATE_FORMAT(CURDATE() + INTERVAL 1 MONTH, '%Y-%m-01')"
|
|||
|
|
)
|
|||
|
|
SUM_E = "CAST(COALESCE(SUM(cr.energy), 0) AS SIGNED)"
|
|||
|
|
CNT_E = "CAST(COUNT(*) AS SIGNED)"
|
|||
|
|
|
|||
|
|
# 组织隔离片段(与 auth::org_condition(user, "cr") / 各处的内联版本逐字一致)
|
|||
|
|
ORG_WHERE_1 = (" AND cr.cabinet_id IN (SELECT c.id FROM cabinets c JOIN projects p "
|
|||
|
|
"ON c.project_id = p.id WHERE p.organization_id = 1)")
|
|||
|
|
ORG_WHERE_999 = (" AND cr.cabinet_id IN (SELECT c.id FROM cabinets c JOIN projects p "
|
|||
|
|
"ON c.project_id = p.id WHERE p.organization_id = 999)")
|
|||
|
|
ORG_WHERE_NONE = " AND 1=0"
|
|||
|
|
ORG_JOIN_1 = " JOIN projects p ON c.project_id = p.id AND p.organization_id = 1"
|
|||
|
|
ORG_JOIN_NONE = " JOIN projects p ON 1=0"
|
|||
|
|
PROJ_ORG_1 = " WHERE p.organization_id = 1"
|
|||
|
|
PROJ_ORG_NONE = " WHERE 1=0"
|
|||
|
|
|
|||
|
|
|
|||
|
|
def show(title, sql):
|
|||
|
|
print("=" * 78)
|
|||
|
|
print(f"### {title}")
|
|||
|
|
print("SQL> " + " ".join(sql.split()))
|
|||
|
|
cur.execute(sql)
|
|||
|
|
cols = [d[0] for d in cur.description]
|
|||
|
|
print(" " + " | ".join(cols))
|
|||
|
|
rows = cur.fetchall()
|
|||
|
|
for r in rows:
|
|||
|
|
print(" " + " | ".join(str(v) for v in r))
|
|||
|
|
print(f" => {len(rows)} 行")
|
|||
|
|
return rows
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------- 原始数据
|
|||
|
|
show(
|
|||
|
|
"0. charge_records 现有行(cabinet_id / start_time / energy)",
|
|||
|
|
"SELECT cr.id, cr.cabinet_id, c.name, cr.start_time, cr.end_time, cr.energy "
|
|||
|
|
"FROM charge_records cr LEFT JOIN cabinets c ON cr.cabinet_id = c.id "
|
|||
|
|
"ORDER BY cr.start_time DESC, cr.cabinet_id",
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------- ① summary
|
|||
|
|
show("1a. summary today(总管理员,无组织条件)",
|
|||
|
|
f"SELECT {SUM_E} FROM charge_records cr WHERE {TODAY}")
|
|||
|
|
show("1b. summary month(总管理员)",
|
|||
|
|
f"SELECT {SUM_E} FROM charge_records cr WHERE {THIS_MONTH}")
|
|||
|
|
show("1c. summary today(组织 1 隔离)",
|
|||
|
|
f"SELECT {SUM_E} FROM charge_records cr WHERE {TODAY}{ORG_WHERE_1}")
|
|||
|
|
show("1d. summary today(不存在组织 999 ⇒ 必须为空集 0)",
|
|||
|
|
f"SELECT {SUM_E} FROM charge_records cr WHERE {TODAY}{ORG_WHERE_999}")
|
|||
|
|
show("1e. summary today(客户侧无组织 ⇒ AND 1=0)",
|
|||
|
|
f"SELECT {SUM_E} FROM charge_records cr WHERE {TODAY}{ORG_WHERE_NONE}")
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------- ② cabinets
|
|||
|
|
RANK = f"""SELECT c.id, COALESCE(c.abstract_id, '') AS abstract_id, c.name,
|
|||
|
|
CAST(COALESCE(cr_today.today_total, 0) AS SIGNED) AS today_energy,
|
|||
|
|
CAST(COALESCE(cr_month.month_total, 0) AS SIGNED) AS month_energy
|
|||
|
|
FROM cabinets c
|
|||
|
|
LEFT JOIN (
|
|||
|
|
SELECT cr.cabinet_id, SUM(cr.energy) AS today_total
|
|||
|
|
FROM charge_records cr
|
|||
|
|
WHERE {TODAY}
|
|||
|
|
GROUP BY cr.cabinet_id
|
|||
|
|
) cr_today ON c.id = cr_today.cabinet_id
|
|||
|
|
LEFT JOIN (
|
|||
|
|
SELECT cr.cabinet_id, SUM(cr.energy) AS month_total
|
|||
|
|
FROM charge_records cr
|
|||
|
|
WHERE {THIS_MONTH}
|
|||
|
|
GROUP BY cr.cabinet_id
|
|||
|
|
) cr_month ON c.id = cr_month.cabinet_id
|
|||
|
|
{{org}}
|
|||
|
|
ORDER BY today_energy DESC, c.id ASC"""
|
|||
|
|
show("2a. cabinets 排行(总管理员)", RANK.format(org=""))
|
|||
|
|
show("2b. cabinets 排行(组织 1 隔离)", RANK.format(org=ORG_JOIN_1))
|
|||
|
|
show("2c. cabinets 排行(客户侧无组织 ⇒ JOIN projects p ON 1=0 ⇒ 空)",
|
|||
|
|
RANK.format(org=ORG_JOIN_NONE))
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------- ③ projects
|
|||
|
|
PROJ = f"""SELECT p.id, p.name,
|
|||
|
|
COUNT(DISTINCT c.id) AS cabinet_count,
|
|||
|
|
CAST(COALESCE(SUM(cr_today.today_total), 0) AS SIGNED) AS today_energy,
|
|||
|
|
CAST(COALESCE(SUM(cr_month.month_total), 0) AS SIGNED) AS month_energy
|
|||
|
|
FROM projects p
|
|||
|
|
LEFT JOIN cabinets c ON p.id = c.project_id
|
|||
|
|
LEFT JOIN (
|
|||
|
|
SELECT cr.cabinet_id, SUM(cr.energy) AS today_total
|
|||
|
|
FROM charge_records cr
|
|||
|
|
WHERE {TODAY}
|
|||
|
|
GROUP BY cr.cabinet_id
|
|||
|
|
) cr_today ON c.id = cr_today.cabinet_id
|
|||
|
|
LEFT JOIN (
|
|||
|
|
SELECT cr.cabinet_id, SUM(cr.energy) AS month_total
|
|||
|
|
FROM charge_records cr
|
|||
|
|
WHERE {THIS_MONTH}
|
|||
|
|
GROUP BY cr.cabinet_id
|
|||
|
|
) cr_month ON c.id = cr_month.cabinet_id
|
|||
|
|
{{org}}
|
|||
|
|
GROUP BY p.id, p.name
|
|||
|
|
ORDER BY today_energy DESC, p.id ASC"""
|
|||
|
|
show("3a. projects 统计(总管理员)", PROJ.format(org=""))
|
|||
|
|
show("3b. projects 统计(组织 1 隔离)", PROJ.format(org=PROJ_ORG_1))
|
|||
|
|
show("3c. projects 统计(客户侧无组织 ⇒ WHERE 1=0)", PROJ.format(org=PROJ_ORG_NONE))
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------- ④ trend
|
|||
|
|
TREND = f"""SELECT {{period}} AS period, {SUM_E} AS energy, {CNT_E} AS charge_count
|
|||
|
|
FROM charge_records cr
|
|||
|
|
WHERE cr.start_time >= DATE_SUB(CURDATE(), INTERVAL {{rng}} DAY){{org}}
|
|||
|
|
GROUP BY period ORDER BY period ASC"""
|
|||
|
|
show("4a. trend granularity=day(总管理员, range=30)",
|
|||
|
|
TREND.format(period="DATE_FORMAT(cr.start_time, '%Y-%m-%d')", rng=30, org=""))
|
|||
|
|
show("4b. trend granularity=week(range=30)",
|
|||
|
|
TREND.format(period="DATE_FORMAT(cr.start_time, '%Y-%u')", rng=30, org=""))
|
|||
|
|
show("4c. trend granularity=month(range=30)",
|
|||
|
|
TREND.format(period="DATE_FORMAT(cr.start_time, '%Y-%m')", rng=30, org=""))
|
|||
|
|
show("4d. trend granularity=day(组织 1 隔离)",
|
|||
|
|
TREND.format(period="DATE_FORMAT(cr.start_time, '%Y-%m-%d')", rng=30, org=ORG_WHERE_1))
|
|||
|
|
show("4e. trend range=-5 **未经夹紧**(DATE_SUB 变成未来 5 天 ⇒ 必然空)",
|
|||
|
|
TREND.format(period="DATE_FORMAT(cr.start_time, '%Y-%m-%d')", rng=-5, org=""))
|
|||
|
|
show("4f. trend range=-5 经 clamp_range ⇒ 1(应含昨天+今天)",
|
|||
|
|
TREND.format(period="DATE_FORMAT(cr.start_time, '%Y-%m-%d')", rng=1, org=""))
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------- ⑤ export
|
|||
|
|
EXPORT = f"""SELECT DATE(cr.start_time) AS stat_date, cr.cabinet_id, c.name AS cabinet_name,
|
|||
|
|
p.name AS project_name,
|
|||
|
|
CAST(COALESCE(SUM(cr.energy), 0) AS SIGNED) AS total_energy,
|
|||
|
|
{CNT_E} AS charge_count
|
|||
|
|
FROM charge_records cr
|
|||
|
|
LEFT JOIN cabinets c ON cr.cabinet_id = c.id
|
|||
|
|
LEFT JOIN projects p ON c.project_id = p.id
|
|||
|
|
WHERE cr.start_time IS NOT NULL{{extra}}
|
|||
|
|
GROUP BY DATE(cr.start_time), cr.cabinet_id, c.name, p.name
|
|||
|
|
ORDER BY stat_date DESC, cr.cabinet_id ASC
|
|||
|
|
LIMIT 100000"""
|
|||
|
|
show("5a. export 明细(无筛选)", EXPORT.format(extra=""))
|
|||
|
|
show("5b. export 明细(end_date=今天必须含当天)",
|
|||
|
|
EXPORT.format(
|
|||
|
|
extra=" AND cr.start_time >= DATE_SUB(CURDATE(), INTERVAL 1 DAY)"
|
|||
|
|
" AND cr.start_time < DATE_ADD(CURDATE(), INTERVAL 1 DAY)"
|
|||
|
|
))
|
|||
|
|
show("5c. export 明细(组织 1 隔离)", EXPORT.format(extra=ORG_WHERE_1))
|
|||
|
|
|
|||
|
|
# ---------------------------------------------------------------- 对照
|
|||
|
|
show("9. 对照:energy_stats 表行数(已无人读写)",
|
|||
|
|
"SELECT COUNT(*) AS energy_stats_rows FROM energy_stats")
|
|||
|
|
|
|||
|
|
cur.close()
|
|||
|
|
conn.close()
|