SQLServer實現(xiàn)Ungroup操作的示例代碼
概要
我們經(jīng)常在SQL Server中使用group by語句配合聚合函數(shù),對已有的數(shù)據(jù)進行分組統(tǒng)計。本文主要介紹一種分組的逆向操作,通過一個遞歸公式,實現(xiàn)ungroup操作。
代碼和實現(xiàn)
我們看一個例子,輸入數(shù)據(jù)如下,我們有一張產(chǎn)品表,該表顯示了產(chǎn)品的數(shù)量。
要求實現(xiàn)Ungroup操作,最后輸出數(shù)據(jù)如下:
代碼和實現(xiàn)
基本思路
要想實現(xiàn)ungroup,顯然需要表格的自連接。自連接的次數(shù)取決于total_count的數(shù)量。
代碼
自連接操作過程中涉及大量的子查詢,為了便于代碼后期維護,我們采用CTE。每次子查詢,total_count自動減一,total_count小于0時,直接過濾掉,該數(shù)據(jù)不再參與查詢。
第1輪查詢
獲取全部total_count 大于0的數(shù)據(jù),即全表數(shù)據(jù)。
with cte1 as ( select * from products where total_count > 0 ),
輸出結(jié)果:
第2輪查詢
第2輪子查詢,以第1輪的輸出作為輸入,進行表格自連接,total_count減1,過濾掉total_count小于0的產(chǎn)品。
with cte1 as ( select * from products where total_count > 0 ), cte2 as ( select * from ( select cte1.id, cte1.name, (cte1.total_count -1) as total_count from cte1 join products p1 on cte1.id = p1.id) t where t.total_count > 0 ) select * from cte2
輸出結(jié)果是:
和第1輪相比較,輸出結(jié)果中沒了Flashlight了,因為它的total_count減1后為0,被過濾了。
第3輪查詢
第3輪子查詢,以第2輪的輸出作為輸入,進行表格自連接,total_count減1,過濾掉total_count小于0的產(chǎn)品。
with cte1 as ( select * from products where total_count > 0 ), cte2 as ( select * from ( select cte1.id, cte1.name, (cte1.total_count -1) as total_count from cte1 join products p1 on cte1.id = p1.id) t where t.total_count > 0 ), cte3 as ( select * from ( select cte2.id, cte2.name, (cte2.total_count -1) as total_count from cte2 join products p1 on cte2.id = p1.id) t where t.total_count > 0 ) select * from cte3
輸出結(jié)果如下:
第4輪查詢
第4輪子查詢,以第3輪的輸出作為輸入,進行表格自連接,total_count減1,過濾掉total_count小于0的產(chǎn)品。
with cte1 as ( select * from products where total_count > 0 ), cte2 as ( select * from ( select cte1.id, cte1.name, (cte1.total_count -1) as total_count from cte1 join products p1 on cte1.id = p1.id) t where t.total_count > 0 ), cte3 as ( select * from ( select cte2.id, cte2.name, (cte2.total_count -1) as total_count from cte2 join products p1 on cte2.id = p1.id) t where t.total_count > 0 ), cte4 as ( select * from ( select cte3.id, cte3.name, (cte3.total_count -1) as total_count from cte3 join products p1 on cte3.id = p1.id) t where t.total_count > 0 ) select * from cte4
輸出結(jié)果:
下一次迭代,compass的total_count也將等于0,被過濾掉,查詢結(jié)果不會再有新的記錄,所以查詢結(jié)束。我們將cte1,cte2,cte3 和 cte4 合并,合并結(jié)果即是所求。
代碼改進
顯然上述代碼過于冗長,如果產(chǎn)品數(shù)量很多,那子查詢的代碼也將大幅度增加。
事實上,從第2輪到第4輪的子查詢,代碼是非常相近的,對于這種情況,無論任何開發(fā)語言,我們都可以采用遞歸的方式進行優(yōu)化處理。對于此類為題,遞歸公式如下:
with CTE as ( initial query -- 初始查詢 union all -- 查詢結(jié)果合并 recursive query -- 遞歸部分,即在查詢中直接引用CTE Recursive terminatation condition -- 遞歸終止條件 )
初始查詢,就是我們的第1輪迭代。遞歸部分,就是我們所謂的相似代碼部分。
對于遞歸終止條件,默認是如果沒有新的記錄參加遞歸,則遞歸終止。本例是按照業(yè)務(wù)邏輯,設(shè)置的終止條件,即total_count需要大于0,這樣也可以做到過濾到最后,不會再有新的記錄參與到遞歸中。
按照上述供述,得到的查詢代碼如下:
with cte as ( select * from products where total_count > 0 union all select * from ( select cte.id, cte.name, (cte.total_count -1) as total_count from cte join products p1 on cte.id = p1.id) t where t.total_count > 0 ) select id, name from cte order by id, name
當我們使用CTE時候,發(fā)現(xiàn)每次查詢的代碼類似,就可以考慮采用上述遞歸公式對代碼進行優(yōu)化。找到初始查詢結(jié)果,在相似的代碼中找到遞歸部分以及遞歸終止條件。
附錄
建表和數(shù)據(jù)初始化代碼
if OBJECT_ID('products', 'U') is not null drop table products create table products ( id int primary key identity(1,1), name nvarchar(50) not null, total_count int not null ) insert into products (name, total_count) values ('Water Bottle', 3), ('Tent', 2), ('Flashlight', 1), ('compass',4)
到此這篇關(guān)于SQLServer實現(xiàn)Ungroup操作的示例代碼的文章就介紹到這了,更多相關(guān)SQLServer Ungroup操作內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SQL查詢服務(wù)器下所有數(shù)據(jù)庫及數(shù)據(jù)庫的全部表
這篇文章主要介紹了SQL查詢服務(wù)器下所有數(shù)據(jù)庫,數(shù)據(jù)庫的全部表,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-05-05sql server中隨機函數(shù)NewID()和Rand()
在SQL語言中,隨機函數(shù)NEWID和rand()用法并不相同,下面就將為您示例分析這兩個隨機函數(shù)的區(qū)別,供您參考,希望對您深入理解SQL函數(shù)能起到作用2015-10-10SQL SERVER2012中新增函數(shù)之字符串函數(shù)CONCAT詳解
SQL Server 2012有一個新函數(shù),就是CONCAT函數(shù),連接字符串非它莫屬。比如在它出現(xiàn)之前,連接字符串是使用"+"來連接,如遇上NULL,還得設(shè)置參數(shù)與配置,不然連接出來的結(jié)果將會是一個NULL。本文就介紹了關(guān)于SQL SERVER 2012中CONCAT函數(shù)的相關(guān)資料,需要的朋友可以參考。2017-03-03SQLServer2005觸發(fā)器提示其他會話正在使用事務(wù)的上下文的解決方法
這篇文章主要介紹了SQLServer2005觸發(fā)器'提示其他會話正在使用事務(wù)的上下文的解決'方法,如果你碰到了這個問題,可以看看下面的解決方法2013-11-11SQL創(chuàng)建數(shù)據(jù)庫時遇到:在數(shù)據(jù)庫master中拒絕了 CREATE DATABASE 權(quán)限
今天在創(chuàng)建數(shù)據(jù)庫的時候,遇到了沒有創(chuàng)建數(shù)據(jù)庫權(quán)限的問題,本文主要介紹了SQL創(chuàng)建數(shù)據(jù)庫時遇到:在數(shù)據(jù)庫master中拒絕了CREATE DATABASE權(quán)限,感興趣的可以了解一下2024-04-04SQLServer行轉(zhuǎn)列實現(xiàn)思路記錄
SQLServer行轉(zhuǎn)列的sql語句有很多,可以使用靜態(tài)的、動態(tài)的、Case When等等,均能實現(xiàn)2014-06-06