ItBJLan 2020-06-28
参数是子查询时,使用 EXISTS 代替 IN
现在我们要查出同时存在于两个表的员工,即田中和铃木,则以下用 IN 和 EXISTS 返回的结果是一样,但是用 EXISTS 的 SQL 会更快:
-- 慢 SELECT * FROM Class_A WHERE id IN (SELECT id FROM CLASS_B); -- 快 SELECT * FROM Class_A A WHERE EXISTS (SELECT * FROM Class_B B WHERE A.id = B.id);
-- 使用连接代替 IN SELECT A.id, A.name FROM Class_A A INNER JOIN Class_B B ON A.id = B.id;
如何找出有销售记录的商品,使用如下 DISTINCT 可以:
SELECT DISTINCT I.item_no FROM Items I INNER JOIN SalesHistory SH ON I. item_no = SH. item_no; 不过更好的方式是使用 EXISTS: SELECT item_no FROM Items I WHERE EXISTS (SELECT * FROM SalesHistory SH WHERE I.item_no = SH.item_no);
-- 这样写需要扫描全表 SELECT MAX(item) FROM Items; -- 这样写能用到索引 SELECT MAX(item_no) FROM Items;
-- 聚合后使用 HAVING 子句过滤 SELECT sale_date, SUM(quantity) FROM SalesHistory GROUP BY sale_date HAVING sale_date = ‘2007-10-01‘; -- 聚合前使用 WHERE 子句过滤 SELECT sale_date, SUM(quantity) FROM SalesHistory WHERE sale_date = ‘2007-10-01‘ GROUP BY sale_date;
SELECT * FROM SomeTable WHERE col * 1.1 > 100; SELECT * FROM SomeTable WHERE SUBSTR(col, 1, 1) = ‘a‘;
SELECT * FROM SomeTable WHERE col_1 > 100 / 1.1;
SELECT * FROM SomeTable WHERE col_1 <> 100;
可以改成以下形式:
SELECT * FROM SomeTable WHERE col_1 > 100 or col_1 < 100;
SELECT * FROM (SELECT sale_date, MAX(quantity) AS max_qty FROM SalesHistory GROUP BY sale_date) TMP WHERE max_qty >= 10;
虽然上面这样的写法能达到目的,但会生成 TMP 这张临时表,所以应该使用下面这样的写法:
SELECT sale_date, MAX(quantity) FROM SalesHistory GROUP BY sale_date HAVING MAX(quantity) >= 10;
SELECT id, state, city FROM Addresses1 A1 WHERE state IN (SELECT state FROM Addresses2 A2 WHERE A1.id = A2.id) AND city IN (SELECT city FROM Addresses2 A2 WHERE A1.id = A2.id);
这段代码用到了两个子查询,也就产生了两个中间表,可以像下面这样写:
SELECT * FROM Addresses1 A1 WHERE id || state || city IN (SELECT id || state|| city FROM Addresses2 A2);
SELECT * FROM film LIMIT 100000, 10
SELECT <cols> FROM profiles inner join (SELECT id form FROM profiles where x.sex=‘M‘ order by rating limit 100000, 10) as x using(id);
SELECT first_name, last_name, homeroom_nbr FROM Students WHERE homeroom_nbr LIKE ‘A-1%‘;
推荐:
SELECT first_name, last_name homeroom_nbr FROM Students WHERE homeroom_nbr LIKE ‘A-1__‘; --模式字符串中包含了两个下划线
SELECT col_1, col_2 FROM SomeTable WHERE col_1 = xxx AND col_2 = xxx
不推荐用:
SELECT * FROM SomeTable WHERE col_1 = xxx AND col_2 = xxx
SELECT * FROM SomeTable WHERE `status` = 0 AND `gmt_create` > 1490025600 AND `gmt_create` < 1490630400 AND `id` > 0 AND `post_id` IN (‘67778‘, ‘67811‘, ‘67833‘, ‘67834‘, ‘67839‘, ‘67852‘, ‘67861‘, ‘67868‘, ‘67870‘, ‘67878‘, ‘67909‘, ‘67948‘, ‘67951‘, ‘67963‘, ‘67977‘, ‘67983‘, ‘67985‘, ‘67991‘, ‘68032‘, ‘68038‘/*... omitted 480 items ...*/) order by id asc limit 200;
在提供 SQL 查询的同时,也贴心地加了一个 EXPLAIN 功能及 SQL 的优化建议,建议各大公司效仿,如图示:
-- 批量插入 INSERT INTO TABLE (id, user_id, title) VALUES (1, 2, ‘a‘),(2,3,‘b‘);
不推荐用:
INSERT INTO TABLE (id, user_id, title) VALUES (1, 2, ‘a‘); INSERT INTO TABLE (id, user_id, title) VALUES (2,3,‘b‘);