JQuick-SQL 子查询:WHERE、SELECT、HAVING 与派生表实践
Meta 描述:掌握 jquick-sql 子查询在 WHERE、SELECT、HAVING、ORDER BY、FROM 和 JOIN 中的真实语法,使用嵌入式 Java 示例查询注册数据集。
标签:jquick-sql、SQL 子查询、EXISTS、IN、标量子查询、Java 跨库查询、异构数据源联邦查询
官网示例:
- FORMULAS 示例页:https://www.jquick.org/jquick-sql
- github 地址:https://github.com/paohaijiao/jquick-sql
前言
子查询让一个查询的结果成为另一个查询的条件、字段或数据来源。jquick-sql 测试已覆盖 WHERE、SELECT、HAVING、ORDER BY、FROM 与 JOIN 中的子查询。它面向已注册的数据集执行,外部数据仍需由上游组件转换后再纳入异构数据源联邦查询流程。
WHERE 中的 IN、EXISTS 与标量比较
sql
SELECT * FROM users
WHERE age > (SELECT AVG(age) FROM users)
SELECT * FROM users u
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id)
标量子查询应返回单个可比较的值;IN 适合用子查询返回候选集合;EXISTS 适合判断关联记录是否存在。
SELECT 与 HAVING 中的子查询
SELECT 可补充关联指标或描述字段:
sql
SELECT u.name,
(SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS order_count
FROM users u
HAVING 可按动态基准过滤聚合结果:
sql
SELECT user_id, SUM(amount) AS total_amount
FROM orders
GROUP BY user_id
HAVING SUM(amount) > (SELECT AVG(amount) FROM orders)
FROM 派生表与关联子查询
派生表让先聚合、后过滤的步骤更清晰:
sql
SELECT tmp.dept_id, tmp.avg_age
FROM (
SELECT department_id AS dept_id, AVG(age) AS avg_age
FROM users
GROUP BY department_id
) AS tmp
WHERE tmp.avg_age > 28
关联子查询引用外层别名时,应确保列元数据、注册表和 SQL 别名遵循项目约定。
可执行 Java 案例
java
import com.github.paohaijiao.engine.JQuickSQL;
import com.github.paohaijiao.statement.JQuickColumnMeta;
import com.github.paohaijiao.statement.JQuickDataSet;
import com.github.paohaijiao.statement.JQuickRow;
import java.util.Arrays;
public class SubqueryDemo {
public static void main(String[] args) {
JQuickSQL sql = JQuickSQL.embedded();
try {
sql.registerTable("users", Arrays.asList(
new JQuickColumnMeta("id", Integer.class, "users"),
new JQuickColumnMeta("name", String.class, "users")
), Arrays.asList(row("id", 1, "name", "Alice"), row("id", 2, "name", "Bob")));
sql.registerTable("orders", Arrays.asList(
new JQuickColumnMeta("user_id", Integer.class, "orders"),
new JQuickColumnMeta("amount", Double.class, "orders")
), Arrays.asList(row("user_id", 1, "amount", 150.0), row("user_id", 1, "amount", 75.0)));
JQuickDataSet result = sql.execute(
"SELECT u.name, (SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS order_count " +
"FROM users u WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id)"
);
result.printTable();
} finally {
sql.shutdown();
}
}
private static JQuickRow row(Object... kv) {
JQuickRow r = new JQuickRow();
for (int i = 0; i < kv.length; i += 2) r.put((String) kv[i], kv[i + 1]);
return r;
}
}
常见问题
**子查询只能写在 WHERE 吗?**不是,项目测试也覆盖 SELECT、HAVING、ORDER BY、FROM 与 JOIN。
**什么时候优先用 EXISTS?**只关心是否存在匹配行时使用。
**子查询会自动访问外部库吗?**不会;它只查询已注册到 jquick-sql 的数据集。
总结与拓展
子查询可把复杂的筛选、指标和派生逻辑留在 SQL 中,减少服务层拼装。对于 Java 跨库查询,关键是先确保上游数据已按统一元数据注册,再利用子查询组织业务逻辑。
Core Advantage
Subqueries compose filters, metrics, and derived datasets using one SQL surface.
Applicable Scenarios
Existence checks, relative benchmarks, lookup enrichment, and grouped analytical queries.