用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/UitbreidenOS/UitKit --skill sql命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Guidelines and instructions for Agent execution state rollback rules
Guidelines and instructions for Agent execution step counters limits
Guidelines and instructions for Agent execution timeout limits setups
基于 SOC 职业分类
正在显示 SKILL.md
| name | sql |
| description | SQL query writing and optimisation: complex joins, window functions, CTEs, indexes, query plans, migration patterns |
CTEs for readability (prefer over nested subqueries):
WITH monthly_revenue AS (
SELECT
DATE_TRUNC('month', created_at) AS month,
SUM(amount) AS revenue
FROM orders
WHERE status = 'completed'
GROUP BY 1
),
revenue_growth AS (
SELECT
month,
revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_revenue,
ROUND(
(revenue - LAG(revenue) OVER (ORDER BY month))
/ NULLIF(LAG(revenue) OVER (ORDER BY month), 0) * 100,
2
) AS growth_pct
FROM monthly_revenue
)
SELECT * FROM revenue_growth ORDER BY month DESC;
Window functions for rankings and running totals:
SELECT
user_id,
order_id,
amount,
-- Running total per user
SUM(amount) OVER (PARTITION BY user_id ORDER BY created_at) AS running_total,
-- Rank within user (dense = no gaps in rank numbers)
DENSE_RANK() OVER (PARTITION BY user_id ORDER BY amount DESC) AS order_rank,
-- Percentile within all orders
PERCENT_RANK() OVER (ORDER BY amount) AS percentile
FROM orders;
Self-joins for hierarchical data:
-- Manager → employee hierarchy
SELECT
e.name AS employee,
m.name AS manager,
e.department
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id
ORDER BY m.name, e.name;
Lateral join for top-N per group:
-- Top 3 orders per customer
SELECT c.name, o.amount, o.created_at
FROM customers c
CROSS JOIN LATERAL (
SELECT amount, created_at
FROM orders
WHERE user_id = c.id
ORDER BY amount DESC
LIMIT 3
) o;
Upsert (INSERT ... ON CONFLICT):
-- PostgreSQL
INSERT INTO user_stats (user_id, login_count, last_login)
VALUES ($1, 1, NOW())
ON CONFLICT (user_id) DO UPDATE SET
login_count = user_stats.login_count + 1,
last_login = NOW();
1. Read the EXPLAIN PLAN first:
EXPLAIN ANALYZE
SELECT * FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'pending' AND o.created_at > NOW() - INTERVAL '7 days';
Signs of a slow query:
Seq Scan on a large table — needs an indexHash Join with large row estimates — consider reducing the result set earlierSort on a non-indexed column — add an index or use a covering indexrows removed by filter — the index isn't selective enough2. Index patterns:
-- Compound index for common filter + sort pattern
CREATE INDEX idx_orders_status_created ON orders (status, created_at DESC);
-- Partial index for a frequent subset
CREATE INDEX idx_orders_pending ON orders (created_at) WHERE status = 'pending';
-- Covering index (includes all selected columns, avoids table lookup)
CREATE INDEX idx_orders_covering ON orders (user_id, status) INCLUDE (amount, created_at);
-- Expression index for computed values
CREATE INDEX idx_users_email_lower ON users (LOWER(email));
3. Avoid N+1 in raw SQL:
-- Bad: one query per user to get their orders
-- (this happens in application code)
-- Good: single query with JOIN
SELECT u.id, u.email, COUNT(o.id) AS order_count, SUM(o.amount) AS total_spent
FROM users u
LEFT JOIN orders o ON o.user_id = u.id AND o.status = 'completed'
GROUP BY u.id, u.email;
-- Always:
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY, -- surrogate key
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
status TEXT NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending', 'completed', 'cancelled')),
amount NUMERIC(10, 2) NOT NULL CHECK (amount >= 0),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes for foreign keys and common filter columns
CREATE INDEX ON orders (user_id);
CREATE INDEX ON orders (status) WHERE status != 'completed'; -- partial
CREATE INDEX ON orders (created_at DESC);
Naming conventions:
snake_case, plural (orders, user_sessions)snake_case (created_at, user_id)idx_{table}_{columns} (idx_orders_user_id_status)fk_{table}_{referenced_table} (fk_orders_users)-- Always wrap in a transaction
BEGIN;
-- Add nullable column first, then backfill, then add NOT NULL constraint
ALTER TABLE orders ADD COLUMN shipping_address TEXT;
UPDATE orders SET shipping_address = 'Unknown' WHERE shipping_address IS NULL;
ALTER TABLE orders ALTER COLUMN shipping_address SET NOT NULL;
-- Add index CONCURRENTLY to avoid locking (PostgreSQL)
CREATE INDEX CONCURRENTLY idx_orders_shipping ON orders (shipping_address);
COMMIT;
Rules for zero-downtime migrations:
CREATE INDEX CONCURRENTLY in PostgreSQLCohort retention:
WITH cohorts AS (
SELECT user_id, DATE_TRUNC('month', MIN(created_at)) AS cohort_month
FROM orders GROUP BY user_id
),
activity AS (
SELECT DISTINCT o.user_id,
DATE_TRUNC('month', o.created_at) AS active_month
FROM orders o
)
SELECT
c.cohort_month,
a.active_month,
DATE_DIFF('month', c.cohort_month, a.active_month) AS month_number,
COUNT(DISTINCT a.user_id) AS users
FROM cohorts c JOIN activity a USING (user_id)
GROUP BY 1, 2, 3 ORDER BY 1, 3;
Funnel analysis:
WITH funnel AS (
SELECT user_id,
MAX(CASE WHEN event = 'signup' THEN 1 END) AS did_signup,
MAX(CASE WHEN event = 'onboard' THEN 1 END) AS did_onboard,
MAX(CASE WHEN event = 'purchase' THEN 1 END) AS did_purchase
FROM events GROUP BY user_id
)
SELECT
COUNT(*) FILTER (WHERE did_signup = 1) AS signups,
COUNT(*) FILTER (WHERE did_onboard = 1) AS onboarded,
COUNT(*) FILTER (WHERE did_purchase= 1) AS purchased
FROM funnel;
Request: "Show me the top 10 customers by revenue in the last 90 days, with their order count, average order value, and whether they've placed an order in the last 7 days."
Expected query:
SELECT
u.id,
u.email,
COUNT(o.id) AS order_count,
SUM(o.amount) AS total_revenue,
ROUND(AVG(o.amount), 2) AS avg_order_value,
MAX(o.created_at) AS last_order_at,
MAX(o.created_at) > NOW() - INTERVAL '7 days' AS active_recently
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.status = 'completed'
AND o.created_at > NOW() - INTERVAL '90 days'
GROUP BY u.id, u.email
ORDER BY total_revenue DESC
LIMIT 10;