最近碰到一些小問題, 本來都是使用PHP來幫忙解決,
但是今天利用了SQL一次解決, 讓我覺得有夠開心的想來分享一下。

描述問題 

現在有三個table, 因為原始設計網站的架構不太彈性, 所使用的class寫法也很虛, 害我等自己echo語法出來慢慢比對,
啊, 一不小心就開始抱怨了起來。

三個table分別是: m_info, m_detail, 和 m_position。

當然, 這是簡化過問題且虛擬的表格。

m_info
mid name
1  王大明
2  李小帥
3  彭小胖
4  林冷生
5  錢快來
m_detail
mid phone
1  12345678
2  11111111
3  22222222
4  33333333
5  44444444
 
m_position
mid position m_date
1 總裁  2001-01-01
2 總裁  2002-01-01
3 總裁  2003-01-01
 

 其中mid為每個table聯繫用的key, 是auto_increasement的一個欄位。

想顯示出的結果為:

mid name phone position
1  彭小胖 22222222 總裁
2  王大明 12345678 總裁
3  李小帥 11111111 總裁
4  林冷生 33333333 NULL
5  錢快來 44444444 NULL

意義是:彭小胖為現任總裁, 因此先取出來擺放在第一位, 接著依照擔任總裁的日期擺放, 最後才擺入沒有擔任過職位的人。

那麼SQL的語法要怎麼寫呢?

SELECT mid, position, phone, CASE WHEN (m_date>='2009-01-01' AND position='會長') THEN 1 ELSE 2 END as m_first, CASE WHEN position is null THEN 2 ELSE 1 END as m_sort FROM m_info JOIN m_detail ON m_detail.mid=m_info.mid LEFT JOIN m_position ON m_position.mid=m_info.mid WHERE GROUP BY mid ORDER BY m_first ASC, m_sort ASC, m_date ASC

紅色字體中的CASE WHEN是這篇文章的重點, 因為我們用條件將總裁職位中欄位date最新的人給取出來(這個條件可以搭配PHP或是ASP.NET等來改變),
先給它一個值, 然後其餘的人給予不同的值, 接著把這個條件alias給m_first這個別名, 最後再使用ORDER BY先進行這個別名的排序。

第二個CASE WHEN目的則是在區分有擔任過職位的人和沒擔任過職位的人, 原理同上方敘述一樣。

GROUP BY則是因為有可能很多人會擔任很多職位, 或是不同時期擔任別的職位之類的, 但是我目前的需求是相同的人只要出現一筆,
於是我利用GROUP BY mid來將相同的人合在一起。

後註:這篇文章讓我寫了三次, 三個不一樣的版本, 而且一直很難上傳...我真的很想對痞克邦罵聲...!

arrow
arrow
    全站熱搜

    andreli 發表在 痞客邦 留言(1) 人氣()