[MySQL / MariaDB] 取得每個group的前N筆資料

最近在工作上為了產報表,需要寫sql去撈每個group的top N筆紀錄。研究了一會兒後最後用了以下的解法。

假設今天有個payment的資料表記錄了每筆交易所涉及的用戶、幣別、金額。

交易id(id) 用戶id(uid) 交易幣別(currency) 金額(amount)
1 11 NTD 800
2 6 NTD 590
3 7 NTD 1020
4 55 USD 24
5 33 USD 27
6 2 USD 25
7 13 JPY 3870
8 10 JPY 2980
9 41 JPY 3780

我們想要取每個幣別的前2筆最大金額的交易記錄,我們可以這樣寫:

SELECT id, uid, currency, amount
FROM (
  SELECT id, uid, currency, amount,
    @counter := IF(@current_currency = currency, @counter + 1, 1) AS counter,
    @current_currency := currency AS current_currency
  FROM payment
  ORDER BY currency, amount DESC
) ordered_result
WHERE counter <= 2;

閱讀更多

FFmpeg剪裁(trim)影片指令

騎車出遊時我幾乎都會戴GoPro在帽子上充當行車記錄器。回家後常常我只想要擷取完整影片的其中一部份,這時候開Premiere等軟體trim完再存檔就感覺有點大材小用了。而且通常trim完存檔時剪輯軟體又包含了轉檔的步驟,這就需要一些等待以及會讓電腦起飛的時間。

利用FFmpeg這個CLI的小工具我們可以只單純做剪裁(trim),而且由於不包含轉檔的動作,所以執行速度很快,電腦也不會起飛。

 

兩種用法

給定 [起始時間] 與 [結束時間] 擷取

ffmpeg -i input.mp4 -ss 01:19:27 -to 01:30:51 -c:v copy -c:a copy output.mp4

給定 [起始時間] 與 [持續時間] 擷取

ffmpeg -i input.mp4 -ss 00:01:10 -t 00:01:05 -c:v copy -c:a copy output.mp4

select...for update再insert造成deadlock的陷阱

最近在寫購票系統,因而踩中了這個坑。這個坑其實對InnoDB的鎖的觀念不熟悉的人會很難發現造成deadlock的原因,因此想特別寫一篇記錄一下,幫助也在開發類似功能的大家少走一點冤望路。

本篇的講解順序會先帶大家重現我之前引發Deadlock的購票功能邏輯,再來說明資料表使用InnoDB引擎下產生如此Deadlock的原因。

 

環境

  • 本篇範例使用的DB是 MariaDB 10.3.7 (開源版的MySQL)
  • 資料表採用預設的 InnoDB 引擎,隔離層級也是預設的 Repeatable Read
  • 範例資料表ticket的schema如下:
CREATE TABLE `ticket` (
  `id`      int(11) NOT NULL AUTO_INCREMENT,
  `show_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `ticket_show_id_IDX` (`show_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4

id是主鍵(PK)、show_id為了之後查詢上的需要,有建非唯一索引(non-unique index)、user_id理論上是外鍵(FK),但這個欄位不是本篇的重點所以忽略他。

  閱讀更多

[Git] commit至未來或過去的特定時間

偶然間在逛別人的repo時發現了對方的contribution竟然這麼酷炫

這絕對不可能是每天勤奮地commit出來的

肯定是可以用程式算好一次性的commit、push

查了一下語法,原來設定GIT_AUTHOR_DATEGIT_COMMITTER_DATE可以調整commit的時間

GIT_AUTHOR_DATE='Wed Dec 30 10:00 2020 +0800' \
GIT_COMMITTER_DATE='Wed Dec 30 10:00 2020 +0800' \
git commit -m "my commit"

這樣就可以commit到特定的時間點去啦

完整圖解Node.js的Event Loop(事件迴圈)

最近當完兵在面試Backend Engineer的缺,想把主力放在Node.js上,因此又把一些Node.js的核心觀念拿出來啃了一遍。網路上太多把前端瀏覽器的Event Loop與Node.js的Event Loop混著講的文章了,因此趁記憶猶新時把Node.js的Event Loop記錄一下,釐清一下觀念。

在開始前先做個小測驗,如果你都能答對代表你的觀念很清晰,這篇文章的內容你應該都懂了。如果答錯了就請繼續往下閱讀吧。

請寫出各個console.log();輸出的順序:

console.log('start');

process.nextTick(function() {
  console.log('nextTick1');
});

setTimeout(function() {
  console.log('setTimeout');
}, 0);

new Promise(function(resolve, reject) {
  console.log('promise');
  resolve('resolve');
}).then(function(result) {
  console.log('promise then');
});

(async function() {
  console.log('async');
})();

setImmediate(function() {
  console.log('setImmediate');
});

process.nextTick(function() {
  console.log('nextTick2');
});

console.log('end');

挑戰一下自己先別往下滑

再往下滑就是解答嘍!! 閱讀更多