不止热门角色,我们为你扩展了更多细分角色分类,覆盖职场提升、商业增长、内容创作、学习规划等多元场景。精准匹配不同目标,让每一次生成都更有方向、更高命中率。
立即探索更多角色分类,找到属于你的增长加速器。
-- 可复用视图:抽取“有效订单”基础集(已支付、未取消、非测试、金额>0)
CREATE VIEW v_orders_valid AS
SELECT
id,
shop_id,
shop_name, -- 若shop_name不在orders表,请在最终查询中改为JOIN店铺表
payment_time,
order_amount
FROM orders
WHERE status = 'paid'
AND cancelled = FALSE
AND COALESCE(is_test, FALSE) = FALSE
AND order_amount > 0;
-- 本月店铺-日期维度成交额与订单数(以支付时间为准),可选按店铺ID列表过滤
-- 使用参数::month_start_date(本月起始00:00:00),:next_month_start_date(下月起始00:00:00),:shop_ids(可选)
SELECT
o.shop_id,
o.shop_name,
CAST(o.payment_time AS DATE) AS order_date,
COUNT(*) AS order_count,
SUM(o.order_amount) AS gross_amount,
AVG(o.order_amount) AS avg_order_value
FROM v_orders_valid AS o
WHERE o.payment_time >= :month_start_date
AND o.payment_time < :next_month_start_date
-- 可选店铺过滤(请以安全的参数绑定方式传入列表)
AND (
:shop_ids IS NULL
OR o.shop_id IN (:shop_ids)
)
GROUP BY
o.shop_id,
o.shop_name,
CAST(o.payment_time AS DATE)
ORDER BY
order_date ASC,
o.shop_id ASC,
gross_amount DESC, -- 金额相同时按订单数降序作为最后的并列打破条件
order_count DESC;
-- 若不使用视图,等价的单条查询(完全展开条件)
SELECT
o.shop_id,
o.shop_name,
CAST(o.payment_time AS DATE) AS order_date,
COUNT(*) AS order_count,
SUM(o.order_amount) AS gross_amount,
AVG(o.order_amount) AS avg_order_value
FROM orders AS o
WHERE o.status = 'paid'
AND o.cancelled = FALSE
AND COALESCE(o.is_test, FALSE) = FALSE
AND o.order_amount > 0
AND o.payment_time >= :month_start_date
AND o.payment_time < :next_month_start_date
AND (
:shop_ids IS NULL
OR o.shop_id IN (:shop_ids)
)
GROUP BY
o.shop_id,
o.shop_name,
CAST(o.payment_time AS DATE)
ORDER BY
order_date ASC,
o.shop_id ASC,
gross_amount DESC,
order_count DESC;
参数示例(应用层计算并绑定):
样例调用逻辑:
若需要从店铺表取店铺名(shop_name 不在 orders):
SELECT
o.shop_id,
s.shop_name,
CAST(o.payment_time AS DATE) AS order_date,
COUNT(*) AS order_count,
SUM(o.order_amount) AS gross_amount,
AVG(o.order_amount) AS avg_order_value
FROM orders AS o
JOIN shops AS s ON s.shop_id = o.shop_id
WHERE o.status = 'paid'
AND o.cancelled = FALSE
AND COALESCE(o.is_test, FALSE) = FALSE
AND o.order_amount > 0
AND o.payment_time >= :month_start_date
AND o.payment_time < :next_month_start_date
AND (
:shop_ids IS NULL
OR o.shop_id IN (:shop_ids)
)
GROUP BY
o.shop_id,
s.shop_name,
CAST(o.payment_time AS DATE)
ORDER BY
order_date ASC,
o.shop_id ASC,
gross_amount DESC,
order_count DESC;
-- 过滤列 + 时间列的复合索引
CREATE INDEX idx_orders_paid_active_month
ON orders (status, cancelled, is_test, payment_time);
-- 按店铺与时间的聚合/过滤支持(便于按店铺ID列表过滤以及分组)
CREATE INDEX idx_orders_shop_time
ON orders (shop_id, payment_time);
-- 若频繁按 payment_time 分区扫描(不按店铺过滤),可增加时间单列索引
CREATE INDEX idx_orders_payment_time
ON orders (payment_time);
-- 说明:
-- 1) 以下语句尽量采用标准SQL(SQL:1999/2008)写法,避免非标准方言;
-- 2) 请将主键列名 id、管理员/软删字段(示例中的 role/is_admin/deleted_at/is_deleted)替换为实际字段;
-- 3) :batch_size / :preview_rows / :sample_rows 为绑定参数(整数),用于控制批量与预览规模;
-- 4) 递归CTE用于将连续点号 .. 反复压缩为单个 .,直到无连续点号为止;
-- 5) 所有更新均限制在最近30天活跃(login_at)且需要修正的用户上,并排除管理员与软删除用户;
-- 6) 批处理按主键升序切分;预览按最近登录时间降序。
/* ========== 预览(按最近登录时间降序)========== */
WITH candidates AS (
SELECT
u.id,
u.login_at,
u.email AS email_before,
/* 计算规范化后的邮箱:lower + trim + 折叠重复点号 */
(
WITH RECURSIVE s(e) AS (
SELECT LOWER(TRIM(u.email))
UNION ALL
SELECT REPLACE(e, '..', '.')
FROM s
WHERE POSITION('..' IN e) > 0
)
SELECT e
FROM s
WHERE POSITION('..' IN e) = 0
FETCH FIRST 1 ROW ONLY
) AS email_after,
CASE WHEN u.email <> LOWER(u.email) THEN 1 ELSE 0 END AS has_uppercase,
CASE WHEN u.email <> TRIM(u.email) THEN 1 ELSE 0 END AS has_trim_spaces,
CASE WHEN POSITION('..' IN u.email) > 0 THEN 1 ELSE 0 END AS has_dup_dots
FROM users u
WHERE
u.login_at >= CURRENT_DATE - INTERVAL '30' DAY
AND u.email IS NOT NULL
AND TRIM(u.email) <> ''
AND (
u.email <> LOWER(u.email) -- 存在大写
OR u.email <> TRIM(u.email) -- 首尾空格
OR POSITION('..' IN u.email) > 0 -- 连续点号
)
/* 管理员排除(按实际字段择一使用) */
AND (u.role IS NULL OR u.role <> 'admin')
AND COALESCE(u.is_admin, 0) = 0
/* 软删除排除(按实际字段择一使用) */
AND u.deleted_at IS NULL
AND COALESCE(u.is_deleted, 0) = 0
)
SELECT
id,
login_at,
email_before,
email_after,
has_uppercase,
has_trim_spaces,
has_dup_dots
FROM candidates
ORDER BY login_at DESC
FETCH FIRST :preview_rows ROWS ONLY;
/* ========== 事务方案(可回滚)========== */
START TRANSACTION;
-- 1) 统计本批将影响的行数(按主键批处理,避免长事务)
WITH candidates AS (
SELECT
u.id,
u.email AS email_before,
(
WITH RECURSIVE s(e) AS (
SELECT LOWER(TRIM(u.email))
UNION ALL
SELECT REPLACE(e, '..', '.')
FROM s
WHERE POSITION('..' IN e) > 0
)
SELECT e
FROM s
WHERE POSITION('..' IN e) = 0
FETCH FIRST 1 ROW ONLY
) AS email_after
FROM users u
WHERE
u.login_at >= CURRENT_DATE - INTERVAL '30' DAY
AND u.email IS NOT NULL
AND TRIM(u.email) <> ''
AND (
u.email <> LOWER(u.email)
OR u.email <> TRIM(u.email)
OR POSITION('..' IN u.email) > 0
)
AND (u.role IS NULL OR u.role <> 'admin')
AND COALESCE(u.is_admin, 0) = 0
AND u.deleted_at IS NULL
AND COALESCE(u.is_deleted, 0) = 0
),
to_update AS (
SELECT id, email_before, email_after
FROM candidates
WHERE email_before <> email_after
),
batch AS (
SELECT *
FROM to_update
ORDER BY id
FETCH FIRST :batch_size ROWS ONLY
)
SELECT COUNT(*) AS affected_rows
FROM batch;
-- 2) 示例前后差异(取本批中的若干行)
WITH candidates AS (
SELECT
u.id,
u.email AS email_before,
(
WITH RECURSIVE s(e) AS (
SELECT LOWER(TRIM(u.email))
UNION ALL
SELECT REPLACE(e, '..', '.')
FROM s
WHERE POSITION('..' IN e) > 0
)
SELECT e
FROM s
WHERE POSITION('..' IN e) = 0
FETCH FIRST 1 ROW ONLY
) AS email_after
FROM users u
WHERE
u.login_at >= CURRENT_DATE - INTERVAL '30' DAY
AND u.email IS NOT NULL
AND TRIM(u.email) <> ''
AND (
u.email <> LOWER(u.email)
OR u.email <> TRIM(u.email)
OR POSITION('..' IN u.email) > 0
)
AND (u.role IS NULL OR u.role <> 'admin')
AND COALESCE(u.is_admin, 0) = 0
AND u.deleted_at IS NULL
AND COALESCE(u.is_deleted, 0) = 0
),
to_update AS (
SELECT id, email_before, email_after
FROM candidates
WHERE email_before <> email_after
),
batch AS (
SELECT *
FROM to_update
ORDER BY id
FETCH FIRST :batch_size ROWS ONLY
)
SELECT
id,
email_before AS old_email,
email_after AS new_email
FROM batch
FETCH FIRST :sample_rows ROWS ONLY;
-- 3) 执行本批更新(按主键批处理)
WITH candidates AS (
SELECT
u.id,
u.email AS email_before,
(
WITH RECURSIVE s(e) AS (
SELECT LOWER(TRIM(u.email))
UNION ALL
SELECT REPLACE(e, '..', '.')
FROM s
WHERE POSITION('..' IN e) > 0
)
SELECT e
FROM s
WHERE POSITION('..' IN e) = 0
FETCH FIRST 1 ROW ONLY
) AS email_after
FROM users u
WHERE
u.login_at >= CURRENT_DATE - INTERVAL '30' DAY
AND u.email IS NOT NULL
AND TRIM(u.email) <> ''
AND (
u.email <> LOWER(u.email)
OR u.email <> TRIM(u.email)
OR POSITION('..' IN u.email) > 0
)
AND (u.role IS NULL OR u.role <> 'admin')
AND COALESCE(u.is_admin, 0) = 0
AND u.deleted_at IS NULL
AND COALESCE(u.is_deleted, 0) = 0
),
to_update AS (
SELECT id, email_before, email_after
FROM candidates
WHERE email_before <> email_after
),
batch AS (
SELECT *
FROM to_update
ORDER BY id
FETCH FIRST :batch_size ROWS ONLY
)
UPDATE users u
SET email = (SELECT b.email_after FROM batch b WHERE b.id = u.id)
WHERE EXISTS (SELECT 1 FROM batch b WHERE b.id = u.id);
-- 4) 若检查无误则提交,否则回滚
-- COMMIT;
-- ROLLBACK;
备注与替代实现:
-- 0) 影响范围预览(建议先按ID范围或时间窗口做预估,避免全表扫描)
-- 说明:如库中布尔类型不是TRUE/FALSE,请按实际取值替换(如 0/1 或 'N'/'Y')。
SELECT COUNT(*) AS candidate_total
FROM coupons c
WHERE c.deleted_at IS NULL
AND c.is_system_reserved = FALSE
AND c.expire_at < CURRENT_DATE
AND (c.usage_count = 0 OR c.status = 'unused')
AND EXISTS (
SELECT 1
FROM activities a
WHERE a.id = c.activity_id
AND (a.status IN ('ended','closed') OR a.end_time < CURRENT_TIMESTAMP)
)
-- 可选分段条件(强烈建议启用以避免锁表和大范围扫描)
AND c.id BETWEEN :start_id AND :end_id;
-- 1) 分段选取本批次候选ID(按过期时间升序;同时间按创建时间升序,再按ID)
-- 注:FETCH FIRST 为标准SQL分页写法;若数据库不支持,请使用等效语法(如 MySQL/PG 使用 LIMIT)。
SELECT c.id
FROM coupons c
WHERE c.deleted_at IS NULL
AND c.is_system_reserved = FALSE
AND c.expire_at < CURRENT_DATE
AND (c.usage_count = 0 OR c.status = 'unused')
AND EXISTS (
SELECT 1
FROM activities a
WHERE a.id = c.activity_id
AND (a.status IN ('ended','closed') OR a.end_time < CURRENT_TIMESTAMP)
)
AND c.id BETWEEN :start_id AND :end_id
ORDER BY c.expire_at ASC, c.created_at ASC, c.id ASC
FETCH FIRST :batch_size ROWS ONLY;
-- 2) 记录审计日志(在同一事务中先插入审计再更新)
-- 说明:使用与更新同一条件确保审计与更新目标一致;batch_id 用于批次回滚与追踪。
INSERT INTO coupon_audit_logs (
coupon_id,
action,
previous_status,
previous_deleted_at,
change_reason,
changed_by,
changed_at,
batch_id
)
SELECT c.id,
'soft_delete',
c.status,
c.deleted_at,
:reason,
:operator_id,
CURRENT_TIMESTAMP,
:batch_id
FROM coupons c
WHERE c.deleted_at IS NULL
AND c.is_system_reserved = FALSE
AND c.expire_at < CURRENT_DATE
AND (c.usage_count = 0 OR c.status = 'unused')
AND EXISTS (
SELECT 1
FROM activities a
WHERE a.id = c.activity_id
AND (a.status IN ('ended','closed') OR a.end_time < CURRENT_TIMESTAMP)
)
AND c.id BETWEEN :start_id AND :end_id;
-- 3) 执行软删除(设置 deleted_at、status、reason)
-- 说明:为避免重复处理,限定 deleted_at IS NULL;与审计条件一致。
UPDATE coupons c
SET c.deleted_at = CURRENT_TIMESTAMP,
c.status = 'inactive',
c.reason = :reason
WHERE c.deleted_at IS NULL
AND c.is_system_reserved = FALSE
AND c.expire_at < CURRENT_DATE
AND (c.usage_count = 0 OR c.status = 'unused')
AND EXISTS (
SELECT 1
FROM activities a
WHERE a.id = c.activity_id
AND (a.status IN ('ended','closed') OR a.end_time < CURRENT_TIMESTAMP)
)
AND c.id BETWEEN :start_id AND :end_id;
-- 4) 本批次影响统计(更新后基于审计日志)
-- 4.1 受影响总量
SELECT COUNT(*) AS affected_rows
FROM coupon_audit_logs
WHERE batch_id = :batch_id
AND action = 'soft_delete';
-- 4.2 按活动分布的影响量(便于评估业务影响)
SELECT c.activity_id,
COUNT(*) AS affected_per_activity
FROM coupons c
WHERE c.id IN (
SELECT al.coupon_id
FROM coupon_audit_logs al
WHERE al.batch_id = :batch_id
AND al.action = 'soft_delete'
)
GROUP BY c.activity_id
ORDER BY affected_per_activity DESC;
-- 5) 回滚指引(基于审计日志恢复之前状态;务必在单独事务中执行)
-- 5.1 执行回滚:恢复之前的 deleted_at、status;reason 写入回滚说明
UPDATE coupons c
SET c.deleted_at = (
SELECT al.previous_deleted_at
FROM coupon_audit_logs al
WHERE al.coupon_id = c.id
AND al.batch_id = :batch_id
AND al.action = 'soft_delete'
),
c.status = (
SELECT al.previous_status
FROM coupon_audit_logs al
WHERE al.coupon_id = c.id
AND al.batch_id = :batch_id
AND al.action = 'soft_delete'
),
c.reason = :rollback_reason
WHERE EXISTS (
SELECT 1
FROM coupon_audit_logs al
WHERE al.coupon_id = c.id
AND al.batch_id = :batch_id
AND al.action = 'soft_delete'
);
-- 5.2 回滚动作审计(可选)
INSERT INTO coupon_audit_logs (
coupon_id,
action,
previous_status,
previous_deleted_at,
change_reason,
changed_by,
changed_at,
batch_id
)
SELECT c.id,
'rollback_soft_delete',
c.status,
c.deleted_at,
:rollback_reason,
:operator_id,
CURRENT_TIMESTAMP,
:batch_id
FROM coupons c
WHERE EXISTS (
SELECT 1
FROM coupon_audit_logs al
WHERE al.coupon_id = c.id
AND al.batch_id = :batch_id
AND al.action = 'soft_delete'
);
分批处理示例(批次1):
键集分页提示(不依赖数据库分页语法的通用方案):
注意事项:
试用后开通会员即可无限使用