今天在做報表的時候遇到乙個問題,想了很長時間沒有解決,後來轉換思路一下子就解決了。具體問題是這樣的,我們公司有一張行業表,總共有四級行業需要維護,具體包括一級行業、二級行業、**行業和四級行業,每個行業之間又存在包含關係,比如四級行業包含於**行業,**行業包含於二級行業,二級行業包含於一級行業,最詭異的地方就是我們把這麼多資訊放在一張表裡維護,只不過額外加了兩個字段以示區分,乙個是行業等級,乙個是父行業,具體的表結構如下:
行業id
行業等級
父行業id
二級行業
二級一級行業
**行業1
**二級行業
**行業2
**二級行業
四級行業1
四級**行業1
四級行業2
四級**行業2
最後的需求是有另外一張表,是用四級行業劃分的,其中有一項費用,最後需要按一級行業統計每個行業的費用。
根據實際業務,為了說明這個問題,筆者在這裡做了乙個模型簡化,假設我們只有兩張表tb_cls和tb_cost,tb_cls包含行業id,行業等級cls,父行業p_id,所有行業(包括一級、二級、**行業都儲存在這張表裡)都包含在內,具體建立出來的表如下(為了讀者閱讀方便,這裡做了乙個簡化:id前面的第一位數代表一級行業編碼,例如121表示屬於一級大行業;整個id的位數代表幾級行業,例如211總共三位表示**行業):
另外一張表,我也做了簡化,只提取其中用到的行業id和費用兩個字段,具體的表內容如下:
我們現在的任務有兩個:彎路:最開始的思路是巢狀,就是根據現實世界的邏輯關係一層一層建立聯絡,第一、建立**行業跟一級行業一一對應關係;
第二、按一級行業統計費用。
select * from tb where id in(select * from tb where)
,沿著這個思路嘗試了很多,首先在select外層宣告的變數內層的巢狀識別不了,內外層建立的變數不能相互訪問,另外乙個這種建立起來的關係,沒有一一對應關係,因為我們用的是in,最終只要存在就可以,所以沒有嚴格的一一對應關係。具體思路如下:
1.1 第1層:select id from tb_cost
1.2 第2層:select p_id from tb_cls where id in(select id from tb_cost) and cls=3
1.3 第3層:select p_id from tb_cls where id in(select p_id from tb_cls where id in(select id from tb_cost) and cls=3) and cls=2
1.4 第4層(最終):select t1.id,t2.id from tb_cls as t1,tb_cost as t2 where t1.id in(select p_id from tb_cls where id in(select p_id from tb_cls where id in(select id from tb_cost) and cls=3) and cls=2)and cls=1;
最終查詢的結果如下:
發現那裡不對了沒有,每個一級行業下面包含所有的**行業,所以這種巢狀方式走不通,同時進一步深入下去研究發現巢狀內外層定義的變數是不能相互互動的,什麼意思呢?select t1.id, var_1 from t1 where p_id in(select id as var_1 from t1)
var_1變數在內層那個select是不可用的。
新思路:基於上面的彎路,筆者換了乙個,假設我們有3張一模一樣的表,通過這3張不同的表來區分各自的邏輯關係,把這3張表看成不同的表,乙個個新增條件,具體思路如下:
2.1 第1層:tb_cls(as t3)**行業跟tb_cost(as t4)建立關聯:t3.id=t4.id and t3.cls=3
2.2 第2層:tb_cls(as t2)二級行業跟tb_cls(as t3)建立關聯:t3.p_id=t2.id and t2.cls=2
2.3 第3層:tb_cls(as t1)一級行業跟tb_cls(as t2)建立關聯:t2.p_id=t1.id and t1.cls=1
最終,建立起來的**行業對應一級行業的對應關係如下:select t1.id,t4.id from tb_cls as t1,tb_cls as t2,tb_cls as t3,tb_cost as t4 where t4.id=t3.id and t3.p_id=t2.id and t2.p_id=t1.id and t3.cls=3 and t2.cls=2 and t1.cls=1;
查詢結果如下,跟我們實際建立的情況一致,第乙個任務(第
一、建立**行業跟一級行業一一對應關係)完成。
解決了第乙個任務,第二個任務就簡單多了,其實就是按照一級行業id加個group by,分一下組就可以,具體語句如下:select t1.id,sum(t4.cost) from tb_cls as t1,tb_cls as t2,tb_cls as t3,tb_cost as t4 where t4.id=t3.id and t3.p_id=t2.id and t2.p_id=t1.id and t3.cls=3 and t2.cls=2 and t1.cls=1 group by t1.id;
查詢結果如下,簡單計算一下一級、二級、**費用是不是查詢出來的值,至此,任務二也圓滿完成。
總結一下,當我們需要解決sql語句的查詢任務的時候,不要一味的選擇深奧的技術、邏輯複雜的語言去解決(像筆者這裡用多層巢狀,最後把自己繞進去了。)首先我們要做的是簡化邏輯,能通過簡單的思路解決複雜的問題本身也是一種能力,在這個基礎上然後基於效能、需求、業務慢慢再繼續優化sql才是我們應該做的。
SQL Server 資料庫內部版本號
資料庫還原或版本公升級出現版本錯誤時可參考 可以利用sql語句檢視本機資料庫版本 select version 如果你不確定是源資料庫的版本,下面的對映表的sql server版本的內部版本號,以便您可以決定您需要的附加成功的最低版本 sql server version internal data...
搜尋資料庫內部資訊和檔案格式
在之前的文章中,我展示過如何用乙個簡單的基於文字格式來儲存記錄,並且對於讀 寫這些記錄又意味著什麼。在這樣乙個系統中搜尋意味著你有相當多的工作要做,因為你需要掃瞄整個檔案。它不會真的為我們工作。所以,我們需要引入索引。索引其實是乙個很簡單的概念。鑑於我們有原始檔案,我們將有以下使用者名稱的索引 基本...
PHP MYSQL 對資料庫內資料實現分頁顯示
title php mysql 對資料庫內資料實現分頁顯示 author stangly wrong 很多php的初學者,都對於web頁面的分頁顯示比較困惑,其實分頁顯示的原理非常簡單,今天又有人在 上問我這個問題。由於順手寫了這一小記,便於眾兄弟朋友翻閱。問題 我的資料庫結構如下 create d...