SQL 藝術(shù):分組去重排序關(guān)聯(lián)

事情交代

在日常嘮嗑前先簡(jiǎn)單說一下本文想要記錄的一次 MySQL 技術(shù)回顧:兩張表茵臭,對(duì)其中一張表進(jìn)行分組去重后疫诽,對(duì)結(jié)果集進(jìn)行排序,然后關(guān)聯(lián)另一張表得到最終的結(jié)果集旦委。

當(dāng)時(shí)推翻重來了幾次奇徒,從中也學(xué)到不少 SQL 知識(shí),因此有必要寫成文章系統(tǒng)的給自己一個(gè)交代缨硝。

OK摩钙,接下來先談些感悟。不喜的請(qǐng)略過查辩,謝謝

日常嘮嗑

自從來到這家公司之后胖笛,一直在維護(hù)后臺(tái)系統(tǒng),其中包括一些舊版頁面的整改宜岛、增加新功能等等长踊。熟悉一個(gè)已有的業(yè)務(wù)邏輯較復(fù)雜的系統(tǒng),我個(gè)人是沒有什么經(jīng)驗(yàn)的萍倡。大二進(jìn)入老師的實(shí)驗(yàn)室后一直做的是外包項(xiàng)目身弊,每一個(gè)外包項(xiàng)目都是全新的,都是自己去從頭搭建列敲,所以其中涉及到的代碼我都非常熟悉阱佛。

因此剛來的時(shí)候,拿到這個(gè)項(xiàng)目的源代碼戴而,開始去了解熟悉凑术,發(fā)現(xiàn)其中用到的語言版本、框架版本等都普遍偏低所意,非常不適應(yīng)淮逊,心里也不免有不少抱怨(當(dāng)我看完李笑來先生的《把時(shí)間當(dāng)做朋友》后催首,深刻明白抱怨一點(diǎn)積極意義都沒有,反而會(huì)打亂自己∽秤ǎ現(xiàn)在遇事也會(huì)成熟不少翅帜,更多的是去積極的看待事物。改變自己挺難的命满,但改變自己很重要)涝滴。最初一段時(shí)間,很不情愿的去看這個(gè)項(xiàng)目的先輩們寫下的對(duì)于現(xiàn)在來說不太優(yōu)秀的代碼胶台,然后對(duì)于組長(zhǎng)指派的迭代任務(wù)我也是依樣畫葫蘆的在原有系統(tǒng)上增加修改歼疮。

覺得很多時(shí)候都在和老系統(tǒng)的代碼作斗爭(zhēng),修 bug诈唬,加補(bǔ)丁韩脏,等等。

沒有思考铸磅,當(dāng)然也不會(huì)有沉淀赡矢,更別提進(jìn)步。 我?guī)е环N不屑阅仔、不愿的態(tài)度接手項(xiàng)目吹散,在經(jīng)過一段消極的工作之旅后,我通過閱讀書籍帶給我的思考對(duì)自己審視了一番八酒。

其實(shí)對(duì)于工程師而言空民,一個(gè)很好的練習(xí),就是試著重構(gòu)一個(gè)有很多問題的老系統(tǒng)羞迷。老系統(tǒng)在很多時(shí)候界轩,因?yàn)樵O(shè)計(jì)初期很多需求不一樣,資源和約束也不一樣衔瓮,隨著時(shí)間推移浊猾,才慢慢顯得不足。而當(dāng)你了解一個(gè)系統(tǒng)要做的東西热鞍,以及所有的缺陷和坑与殃,試著去思考:如果是你來重新設(shè)計(jì)這個(gè)系統(tǒng),你會(huì)怎么做碍现?一定會(huì)有哪些選擇?一定會(huì)避免哪些選擇米奸?
這樣的練習(xí)昼接,在腦海里一遍遍地過,即使你沒有時(shí)間和精力去真的重構(gòu)悴晰,也會(huì)對(duì)你能力的提高有很大的幫助慢睡。而有機(jī)會(huì)的時(shí)候逐工,從一些小的地方著手,試圖一點(diǎn)點(diǎn)地在力所能及的范圍內(nèi)改進(jìn)系統(tǒng)漂辐。這比鄙視舊系統(tǒng)泪喊,然后不斷寫出更爛的代碼、把系統(tǒng)變得更糟糕要好很多髓涯。

這段話來自微信公眾號(hào):嘀嗒嘀嗒袒啼,文章題為《為什么有的程序員覺得自己是個(gè)打雜的?

當(dāng)時(shí)看到這標(biāo)題的時(shí)候總感覺是寫給我的纬纪,不過現(xiàn)在明白醒悟也不晚蚓再,幸運(yùn)如我,不是嗎 :)

嘮嗑結(jié)束了包各,接下來是這次的正文。

需求場(chǎng)景

事情是這樣的,上周五運(yùn)營(yíng)人員提了一個(gè)需求(僅為一個(gè)例子):希望在用戶列表頁面能對(duì)登錄時(shí)間進(jìn)行過濾排序宙项,比如想要看到3月1日至3月2日登錄過的用戶爆存,且根據(jù)這段時(shí)間內(nèi)用戶的登錄時(shí)間進(jìn)行降序排列。結(jié)合數(shù)據(jù)庫(kù)的情況护姆,這個(gè)需求要用到兩張表(一個(gè)用戶表:user矾端,一個(gè)用戶登錄記錄表:user_login_record)。

user

user_id nick
1 amy
2 bob

user_login_record

id user_id login_time
1 1 2017-03-01 00:00:00
2 1 2017-03-01 20:00:00
3 2 2017-03-01 05:00:00
4 2 2017-03-01 09:00:00
5 2 2017-03-01 16:00:00

心路歷程

如果某個(gè)用戶在過濾的時(shí)間段內(nèi)登錄過兩次及以上签则,那么一定會(huì)遇到需要分組去重的問題须床。

版本1.0

執(zhí)著于使用 DISTINCT 來完成去重的操作,但這樣只能對(duì)某一列進(jìn)行去重渐裂,且無法列出其他列豺旬,也就沒法在一個(gè) SQL 中再進(jìn)行排序操作。

SELECT
    DISTINCT user_id
FROM
    user_login_record
WHERE
    login_time BETWEEN '2017-03-01' AND '2017-03-02'
GROUP BY
    user_id
版本2.0

經(jīng)人提醒柒凉,可以使用 聚合函數(shù) 來達(dá)到去重的效果族阅。

SELECT
    user_id, MAX(login_time) as max_login_time
FROM
    user_login_record
WHERE
    login_time BETWEEN '2017-03-01' AND '2017-03-02'
GROUP BY
    user_id
ORDER BY
    max_login_time DESC

這里拿到了已去重排好序的滿足過濾條件的用戶 ID 以及那個(gè)時(shí)間段內(nèi)最近一次登錄時(shí)間,接下來就是將 user 表中用戶信息獲取到即可

user_id max_login_time
1 2017-03-01 20:00:00
2 2017-03-01 16:00:00

可以通過后端腳本將 user_id 拼接起來作為查詢條件

SELECT
    user_id,
    nick
FROM
    user
WHERE
    user_id IN (1, 2)
ORDER BY
    FIELD(user_id, 1, 2)
user_id nick
1 amy
2 bob

由于兩個(gè)結(jié)果集的順序是一樣的膝捞,因此登錄時(shí)間也是一一對(duì)應(yīng)的坦刀,所以對(duì)其中一個(gè)結(jié)果集循環(huán),對(duì)應(yīng)另一個(gè)結(jié)果集中索引對(duì)應(yīng)的值合并蔬咬。

MySQL 知識(shí)點(diǎn):FIELD

  • 作用:自定義排序

  • 格式

FIELD(value, str1, str2...)
  • 場(chǎng)景

由于 MySQL 并不會(huì)按 IN 中傳入的參數(shù)順序輸出結(jié)果集鲤遥,因此需要用到 FIELD 來自定義排序,只需傳入的參數(shù)與 IN 中傳入的參數(shù)完全相同即可

SQL 語句有多重要~

在減少數(shù)據(jù)庫(kù)連接與減少數(shù)據(jù)庫(kù)執(zhí)行負(fù)擔(dān)兩者間進(jìn)行權(quán)衡林艘。運(yùn)用得好可以提升性能盖奈,減少代碼『總之钢坦,多思考究孕。

晚安,各位爹凹,床上那位催著睡覺了厨诸。。禾酱。


首發(fā)于個(gè)人博客 StephenCode

同步在:

知乎專欄:黑白之間

簡(jiǎn)書專題:黑白之間

SegmentFault 專欄:黑白之間

微信公眾號(hào):黒白之間

wechat.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末微酬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子宇植,更是在濱河造成了極大的恐慌得封,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件指郁,死亡現(xiàn)場(chǎng)離奇詭異忙上,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)闲坎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門疫粥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腰懂,你說我怎么就攤上這事梗逮。” “怎么了绣溜?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵慷彤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我怖喻,道長(zhǎng)底哗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任锚沸,我火速辦了婚禮跋选,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘哗蜈。我一直安慰自己前标,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布距潘。 她就那樣靜靜地躺著炼列,像睡著了一般。 火紅的嫁衣襯著肌膚如雪音比。 梳的紋絲不亂的頭發(fā)上唯鸭,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音硅确,去河邊找鬼目溉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛菱农,可吹牛的內(nèi)容都是我干的缭付。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼循未,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼陷猫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起的妖,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤绣檬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后嫂粟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娇未,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年星虹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了零抬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宽涌,死狀恐怖平夜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卸亮,我是刑警寧澤忽妒,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站兼贸,受9級(jí)特大地震影響段直,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寝受,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一坷牛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧很澄,春花似錦京闰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至讯蒲,卻和暖如春痊土,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背墨林。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工赁酝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留犯祠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓酌呆,卻偏偏與公主長(zhǎng)得像衡载,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子隙袁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容