曾經寫 SQL 寫得嚇嚇叫,但是自從一陣子沒接觸之後,整個退化得特別厲害,所以有必要來寫一下筆記,讓未來如果長久沒寫 SQL,還可以回憶一下。
速查資源:
https://devhints.io/sql-join
https://devhints.io/knex
SELECT EXISTS 子查詢 - 檢查帳號+密碼是否存在
SELECT EXISTS(SELECT id FROM members WHERE uid = ? AND passowrd = ?) AS is_exists;
LIMIT, 分頁功能及基本要素
製作分頁的基本要素有下列:
- 每一頁長度限制: (傳進) limit
- 目前分頁: (傳進) page
- 在以上條件之下,有幾頁: pageSize
- 總資料數量: total
- 該頁資料: data
- linit: limit 要大於 1
- page: 務必了解是從 0 開始算
- pageSize: 就算是 0 筆資料,也是總共 1 頁
- total: 選取所有資料大小
SELECT * FROM warehouse GROUP BY id ORDER BY create_at DESC LIMIT ?, ?;
假設 (?, ?) 為 5, 20 ,這裡就可以了解是從第 5 頁開始,後 20 筆資料,如果使用 knex ORM 查詢,分頁效果會像:
knex("warehouse").offset(page*limit).limit(limit)
也就是,從第 5*20 筆資料開始偏移,查 20 筆資料。
查詢大小,並製作 pageSize, total
SELECT count(*) as length FROM warehouse;
然後,該 length 即為 toatl,pageSize 是:
(length <= limit) ? 1 : Math.ceil(length / limit, 1)
也就是如果除出來小於 limit,得到的結果會小於 1 ,所以如果筆數小於限制大小,就直接給他 1 的結果,如果大於 limit,全部都使用無條件進位。
HAVING, WHERE 差異
group by 是一種 summary column 的做法, having 是給 group by 指令去搜尋條件用的,簡單的說:
WHERE 是給 SELECT 用的, HAVING 是給 GROUP BY 用的。
IF IS NULL - 如果為空,就回傳 0
SELECT IF(SUM(balance) IS NULL, 0 ,SUM(balance)) as available FROM virtualcashoffer WHERE expire > NOW()
上面這是一段檢查時效性購物金的做法,可能會有如果購物金都過期,則回傳會變空的情形,此時可以用這個方法解決,讓 null 變成 0。
DATE, INTERVAL - 日期增減
減法:
SELET * FROM virtualcashoffer WHERE expire > DATE_SUB(NOW(), INTERVAL 3 MONTH)
SELET * FROM virtualcashoffer WHERE expire > NOW() AND DATE_ADD(NOW(), INTERVAL 1 MONTH) > expire
JOIN + 子查詢 - 特殊結構查詢 JOIN 方式
SELECT * FROM products p LEFT JOIN (SELECT * FROM spec GROUP BY product_id) s ON s.product_id = p.id
WHERE FOR UPDATE - 更新最後查詢時間的做法
START TRANSACTION; SELECT * FROM orders o WHERE o.id IN (?) ORDER BY o.id FOR UPDATE; UPDATE orders SET last_export_at = NOW() WHERE id IN (?); COMMIT;
DISTINCT - 試著查詢不重複的 id 有幾個?
SELECT count(DISTINCT warehouse_group_id) as length FROM warehouse
查找最大元素的理解
要找最後一筆插入的元素,跟去找目前最新的元素,是不一樣的事,前者會常常使用 LAST INSERT 的方式去找,但這件事的前提事你需要在同 SECTION 做 INSERT ,才可以查到。
但如果要查找最新的元素,基於 AUTO INCREMENT 的情形下,只需要找 MAX(id) 就可以了。
SELECT MAX(id) FROM warehouse
SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '[DB Name]' AND TABLE_NAME = '[Table Name]';
重設 AUTO INCREMENT
強制重設
ALTER TABLE table_name AUTO_INCREMENT = 1;
截斷表
TRUNCATE TABLE table_name;
WHERE IN - 多重資料一次完成查詢
SELECT * FROM product WHERE id IN (?);
MariaDB JSON 使用 - 包含資料在陣列中
SELECT JSON_CONTAINS( (SELECT JSON_EXTRACT(CONCAT('[',replace(group_concat(product_spec_id),',',','),']'), '$') FROM orderproducts WHERE order_id = 2), -- 先做子查詢找出該訂單購買哪些項目 (orderproducts) JSON_EXTRACT(d.condition_value, '$'))
鎖表機制
LOCK TABLES warehouse write; -- 操作之後 UNLOCK TABLES;
JOIN 圖表
Inner join | ∩ |
Left outer join | A + ∩ |
Right outer join | ∩ + B |
Full outer join | A + ∩ + B |
沒有留言:
張貼留言