今天被人問到這樣乙個問題,整理出來給大家也參考一下
假設有如下這樣一張**:
這裡的資料,具有如下的特徵:在乙個departmentid中,可能會有多個name,反之也是一樣。就是說name和departmentid是多對多的關係。
現在想實現這樣乙個查詢:按照departmentid排完序之後(第一步),再獲取name列的不重複值(第二步),而且要保留在第一步後的相對順序。以本例而言,應該返回三個值依次是:acb
我們首先會想到下面這樣乙個寫法
select
distinct name from sample order
by departmentid
從語義上說,這是很自然的。但是很可惜,這個語句根本無法執行,錯誤訊息是:
這個錯誤的意思是,如果使用了distinct(去重複值),則出現在orderby後面的字段,必須也出現在select後面,但如果departmentid如果也真的出現在select後面,顯然是不會有重複值的,所以結果肯定也是不對的。
那麼,既然disinct 與orderby結合起來用會有這個的乙個問題,我們是否有可能變通一下,例如下面這樣:
select
distinct a.name
from (select
top 100 percent name from sample order
by departmentid) a
更好的
想比較之前的寫法,我們用到了子查詢技術。同樣從語義上看,仍熱是很直觀明了的。我想先按照departmentid進行排序, 然後再去重複值。但是返回到結果是下面這樣的:
雖然確實去除了重複值,但返回的順序卻是不對的。我們希望是先按照departmentid排序之後,然後去除重複值,並且保留排序後的相對順序。
為什麼會出現上面這個結果呢?其實是因為distinct本身是會做排序的,而且這個行為是無法更改的(下圖的執行計畫中可以看到這一點)。所以其實我們之前做的order by在這裡會失去意義。【實際上,如果觀察ado.net entity framework等orm工具中生成的類似的乙個查詢,它會自動丟棄order by的設定】
那麼,這樣的情況下,是不是就不可能實現需求了呢?雖然說,這個需求並不多見,絕大部分時候,distinct作為最後乙個操作,做一次排序是合乎情理的。
我是這樣考慮到,既然distinct的這個行為是內建的,那麼是否可以繞過這個操作呢?最終我用的乙個解決方案是:我能不能把每個name都編上乙個編號,例如有兩個a的話,第乙個a我為它編號為1,第二個編號為2,以此類推。然後,查詢的時候,我先排序,然後篩選那些編號為1的name,這樣其實也就實現了去重複值了。
sql server 2005開始提供了乙個row_number的功能,結合這個功能,我實現了下面這樣的查詢:
select a.name from
(select
top 100 percent
name,departmentid,row_number() over(partition by name order
by departmentid) row
from sample order
by departmentid) a
where a.row=1
order
by a.departmentid
然後,我得到了下面這樣的結果,我推敲下來,這應該是符合了之前提到的這個需求的
相比較而言,這個查詢的效率會低一些,這個是可以預見的(可以通過下圖看出一點端倪)。但如果需求是硬性的,那麼犧牲一些效能也是不奇怪的。當然,我們可以再研究看看是否有更優的一些寫法。無論如何,使用內建標準的實現,通常都是相對較快的。
乙個printf引發的問題
牛客網上的乙個題目 intmain 看起來挺簡單的,牽扯的東西比較多。這是我的思路 printf函式執行的時候,會先把這三個數字壓入棧裡,然後再執行列印。壓入棧的時候按照資料本身的長度來,首先把c和b壓入,並且每乙個都是8個位元組 printf自動轉化為double 然後再壓入a是4個位元組。然後再...
乙個索引引發的問題
215 上了乙個大表的組合索引,引發了查詢sql的執行計畫混亂,最終cpu充到100 業務系統掛掉,庫也幾乎宕掉。1,為什麼建了索引後,oracle執行計畫會亂掉,而且選擇了乙個最慢的執行計畫?dba答覆 表關聯!關聯表越多,oracle選擇執行計畫出錯的概率變大!如何防止此類事件 上索引之前,先固...
乙個content type引發的問題
背景介紹 問題 報警監控顯示專案的活動介面異常並報錯,提示json decode解析異常,但不必現,無法立刻判斷原因。先介紹下我們的資料傳遞流程 監控時常顯示專案的某個介面報錯異常,報警提示如下 圖2.報警郵件 過程分析 很明顯,json decode post result 出錯,解析的資料格式非...