第一条查询
一条查询只回答一个问题:我要哪些行的哪些列? 最短的问法是 SELECT *——所有列——再用 FROM 指一张表。
1
-- Every column of every product. Run it with F9 or Ctrl/Cmd + Enter.
SELECT *
FROM products
LIMIT 20;
结果 — 共 20 行,这里是前 5 行
| id | category_id | name | description | sku | price | cost | stock_quantity | weight_kg | attributes | is_active | created_at | updated_at |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 16 | Glass Orchard (Paperback ed.) | Glass Orchard (Paperback ed.) — built to last. | SKU-00001 | 913.72 | 443.95 | 179 | 6.18 | {"color":"green","warranty_months":12,"material":"fabric"} | 1 | 2024-01-13 07:13:52 | 2024-01-13 07:13:52 |
| 2 | 17 | Luma The Gene | Luma The Gene — built to last. | SKU-00002 | 332.64 | 161.72 | 83 | 5.893 | {"color":"silver","warranty_months":24,"material":"steel"} | 1 | 2022-06-16 08:45:20 | 2022-06-16 08:45:20 |
| 3 | 21 | Quill Helmet | Quill Helmet — designed for daily use. | SKU-00003 | 196.26 | 118.25 | 399 | 8.261 | {"color":"silver","warranty_months":24} | 1 | 2022-08-26 20:06:03 | 2022-08-26 20:06:03 |
| 4 | 16 | Kite Glass Orchard 3 | Kite Glass Orchard 3 — built to last. | SKU-00004 | 1719.68 | 845.91 | 243 | 5.263 | {"color":"silver","warranty_months":24} | 0 | 2022-07-19 11:34:27 | 2022-07-19 11:34:27 |
| 5 | 17 | The Gene (3rd ed.) | The Gene (3rd ed.) — a dependable everyday choice. | SKU-00005 | 122.8 | 69.5 | 357 | 1.898 | {"color":"red","warranty_months":36,"material":"aluminium"} | 1 | 2022-05-21 10:53:40 | 2022-05-21 10:53:40 |
浏览器会另开一个标签页打开 Planche,示例数据库已经载入,这条查询也已经放好。本页其他示例都会复用同一个标签页;在你按下 F9 之前,什么都不会执行。
* 表示“所有列”,LIMIT 20 表示“最多返回 20 行”。如果只是查看表的结构,就不必读取 products 的数千行数据;这些数据还需要传输和渲染。
Planche 也会限制结果行数(设置 › 安全 › 行数上限)。不过在查询中明确写 LIMIT,可以按预期控制数据库读取的数据量。
选择列
SELECT * 适合先查看表。确定需要哪些数据后,应明确列出列名,这样结果更易读,传输的数据也更少。
2
SELECT name, sku, price, stock_quantity
FROM products
LIMIT 20;
结果 — 共 20 行,这里是前 5 行
| name | sku | price | stock_quantity |
|---|---|---|---|
| Glass Orchard (Paperback ed.) | SKU-00001 | 913.72 | 179 |
| Luma The Gene | SKU-00002 | 332.64 | 83 |
| Quill Helmet | SKU-00003 | 196.26 | 399 |
| Kite Glass Orchard 3 | SKU-00004 | 1719.68 | 243 |
| The Gene (3rd ed.) | SKU-00005 | 122.8 | 357 |
SELECT 中的列顺序就是结果列的顺序,与表本身的列顺序无关。要更改结果列名,可使用 AS。
用 WHERE 筛选行
SELECT 挑列,WHERE 挑行。它接受一个条件,只留下条件为真的那些行。
3
SELECT name, price, stock_quantity
FROM products
WHERE price > 100
LIMIT 20;
结果 — 共 20 行,这里是前 5 行
| name | price | stock_quantity |
|---|---|---|
| Lean Startup (Deluxe ed.) | 107.37 | 84 |
| Pixel Sofa | 108.18 | 7 |
| Terra Pillow Pro | 113.67 | 0 |
| Pulse LED Strip | 114.86 | 480 |
| Brief Answers (3rd ed.) | 117.96 | 194 |
比较运算符都是你能猜到的:=、<>(或 !=)、<、<=、>、>=。其中两个和别的语言不一样,每个人都会被绊一次:
- 相等只写一个
=,不是==。 - 没有任何东西等于 NULL,NULL 自己也不行。不管有多少商品没记重量,
WHERE weight_kg = NULL一行都匹配不到。你要的判断是IS NULL/IS NOT NULL。下一课会正经讲它。
用 ORDER BY 排序
没有 ORDER BY,行回来的顺序是未定义的。如果你在意顺序,就写出来;如果没写,就别指望眼前看到的这个顺序,因为索引一变、数据一变,它立刻就会变。
4
SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 20;
结果 — 共 20 行,这里是前 5 行
| name | price |
|---|---|
| Glide GPS Watch Pro | 2484.4 |
| Terra 3D Puzzle | 2481.77 |
| Aria Castle Kit | 2479.41 |
| Aria LED Strip Pro | 2463.41 |
| Nova Brief Answers | 2445.49 |
DESC 从大到小,ASC(默认)从小到大。注意这条查询里的组合:ORDER BY price DESC 配上 LIMIT 20,就是"前 20 名"的写法。在脑子里把两个子句调个个儿,就能看出顺序为什么重要——数据库是先把全部排好序,再取前二十行。
在 Planche 里你很少需要手写这一条。点结果网格的列标题,它会在服务端对整张表排序,按 升序 → 降序 → 取消 循环。看看它生成的 SQL,也是检查自己写法的好办法。
按多个列排序
写上几个排序键,后一个负责打破前一个留下的平局。
5
SELECT category_id, name, price
FROM products
ORDER BY category_id, price DESC
LIMIT 30;
结果 — 共 30 行,这里是前 5 行
| category_id | name | price |
|---|---|---|
| 2 | Aria Notebook | 2116.4 |
| 2 | Ember Laptop Plus | 2087.98 |
| 2 | Sol Notebook | 1982.34 |
| 2 | Sol Ultrabook | 1942.47 |
| 2 | Nimbus Ultrabook | 1933.06 |
这会把商品按分类聚在一起,并在每个分类内部把最贵的放前面。读起来就是"先按分类,再按价格降序"——正是你会脱口而出的那句话。
表达式和别名
SELECT 后面不一定是列。可以是算术、函数调用,或任何能为每一行产生一个值的东西——而 AS 给这个结果起名字。
6
SELECT name,
price,
cost,
ROUND(price - cost, 2) AS margin
FROM products
WHERE is_active = 1
ORDER BY margin DESC
LIMIT 15;
结果 — 共 15 行,这里是前 5 行
| name | price | cost | margin |
|---|---|---|---|
| Ember Tab Plus | 2412.93 | 984.94 | 1427.99 |
| Aria LED Strip Pro | 2463.41 | 1098.69 | 1364.72 |
| Luma Denim Jacket Pro | 2357.59 | 993.24 | 1364.35 |
| Drift A Winter Letter | 2422.5 | 1082.43 | 1340.07 |
| Nova Brief Answers | 2445.49 | 1108.09 | 1337.4 |
ROUND(price - cost, 2) AS margin 算出了一个表里根本不存在的列,而 margin 这个名字随后可以在 ORDER BY 里用。但它在 WHERE 里用不了,这一点经常把人绊住。原因在于数据库执行子句的顺序:
FROM -> WHERE -> SELECT -> ORDER BY -> LIMIT
轮到 ORDER BY 时,SELECT 已经把 margin 算出来了。而 WHERE 运行时它还不存在,所以 WHERE margin > 50 是个错误——你只能把表达式重写一遍,或者把整条查询再包一层。把这个顺序记住;WHERE 在分组前筛行、HAVING 在分组后筛,也是同一个顺序解释的,那是再下一课的内容。
现在你能做什么
只用这几个子句就能回答不少真实问题:最贵的二十个商品、所有缺货的商品、在售目录里利润率最高的那些。还做不到的是跨两张表提问——哪个客户下了哪张订单——那就是连接要解决的事。
继续之前,把上面例子里的数字和列名改一改再跑一遍。网格是原地刷新的,试错的循环很快。