java动态交叉表,SqlServer如何生成动态交叉表查询
為了說明問題,我們用SqlServer自帶的事例數據庫(Northwind)來進行驗證,所有的例子請放到Northwind中運行,我可能會省略Use語句,所引用的表,都是Northwind中的,下面我就不再說明了
這里指的交叉表,就是象Access的交叉表查詢一樣的效果,比如Employees表中City字段代表了城市的名稱,TitleOfCourtesy代表稱呼,我們希望按照City和TitleOfCourtesy的情況來統計ReportsTo字段的合計數(本統計沒有任何實際意義,只是挑選一些記錄包含重復內容的字段來說明情況),并顯示成以下格式:(TitleOfCourtesy作為行,City作為列)
探討這個問題之前,我們首先來看一下如何建立靜態的交叉表,也就是說列數固定的交叉表,這種情況其實只要一句簡單的Select查詢就可以搞定:
SELECT
TitleOfCourtesy,
SUM
(
CASE
City
WHEN
'
London
'
THEN
ReportsTo
ELSE
NULL
END
)
AS
[
London?City
]
,
SUM
(
CASE
City
WHEN
'
Redmond
'
THEN
ReportsTo
ELSE
NULL
END
)
AS
[
Redmond?City
]
,
SUM
(
CASE
City
WHEN
'
Seattle
'
THEN
ReportsTo
ELSE
NULL
END
)
AS
[
Seattle?City
]
FROM
Employees
GROUP
BY
TitleOfCourtesy
其中利用了CASE語句判斷,如果是相應的列,則取需要統計的ReportsTo數值,否則取NULL,然后再合計
其中有兩個常見問題說明一下:
a、用NULL而不用0是有道理的,假如用0,雖然求和函數SUM可以取到正確的數,但類似COUNT函數(取記錄個數),結果就不對了,因為Null不算一條記錄,而0要算,同理空字串("")也是這樣,總之在這里應該用NULL,這樣任何函數都沒問題。
b、假如在視圖的設計界面保存以上的查詢,則會報錯“沒有輸出列”,從而無法保存,其實只要在查詢前面加上一段:Create View ViewName AS ...,ViewName是你準備給查詢起的名稱,...就是我們的查詢,然后運行一下,就可以生成視圖了,對于其他一些設計器不支持的語法,也可以這樣保存。
以上查詢作用也很大,對于很多情況,比如按照季度統計、按照月份統計等列頭內容固定的情況,這樣就行了,但往往大多數情況下列頭內容是不固定的,象City,用戶隨時可能刪除、添加一些城市,這種情況,我們就需要用存儲過程來解決:
總體思路其實很簡單,首先檢索列頭信息,形成一個游標,然后遍歷游標,將上面查詢語句里Case判斷的內容用游標里的值替代,形成一條新的Sql查詢,然后執行,返回結果,就可以了,以下是我寫的一個存儲過程,供大家參考:
CREATE
procedure
CorssTab
@strTabName
as
varchar
(
50
)
=
'
Employees
'
,
--
此處放表名
@strCol
as
varchar
(
50
)
=
'
City
'
,
--
表頭分組依據字段
@strGroup
as
varchar
(
50
)
=
'
TitleOfCourtesy
'
,
--
分組字段
@strNumber
as
varchar
(
50
)
=
'
ReportsTo
'
,
--
被統計的字段
@strSum
as
varchar
(
10
)
=
'
Sum
'
--
運算方式
AS
DECLARE
@strSql
as
varchar
(
1000
),
@strTmpCol
as
varchar
(
100
)
EXECUTE
(
'
DECLARE?corss_cursor?CURSOR?FOR?SELECT?DISTINCT
'
+
@strCol
+
'
from
'
+
@strTabName
+
'
for?read?only
'
)
--
生成游標
begin
SET
nocount
ON
SET
@strsql
=
'
select
'
+
@strGroup
+
'
,
'
+
@strSum
+
'
(
'
+
@strNumber
+
'
)?AS?[
'
+
@strSum
+
'
of
'
+
@strNumber
+
'
]
'
--
查詢的前半段
OPEN
corss_cursor
while
(
0
=
0
)
BEGIN
FETCH
NEXT
FROM
corss_cursor
--
遍歷游標,將列頭信息放入變量@strTmpCol
INTO
@strTmpCol
if
(
@@fetch_status
<>
0
)
break
SET
@strsql
=
@strsql
+
'
,
'
+
@strSum
+
'
(CASE
'
+
@strCol
+
'
WHEN
'''
+
@strTmpCol
+
'''
THEN
'
+
@strNumber
+
'
ELSE?Null?END)?AS?[
'
+
@strTmpCol
+
'
'
+
@strCol
+
'
]
'
--
構造查詢
END
SET
@strsql
=
@strsql
+
'
from
'
+
@strTabname
+
'
group?by
'
+
@strGroup
--
查詢結尾
EXECUTE
(
@strsql
)
--
執行
IF
@@error
<>
0
RETURN
@@error
--
如果出錯,返回錯誤代碼
CLOSE
corss_cursor
DEALLOCATE
corss_cursor
RETURN
0
--
釋放游標,返回0表示成功
end
GO
幾點說明:
a、這是一個通用存儲過程,使用時@strTabName、@strCol、@strGroup、@strNumber、@strSum幾個變量設置一下就可以用到其他表上,其中結果集的第二列我加了個合計列
b、為了測試方便,我在存儲過程中設置了默認值,就是前面提到的Employees表,這樣直接運行時就可以出來我上面提到的結果。
c、使用時,可以把上面的代碼復制到企業管理器的查詢設計界面Sql窗格,或者查詢分析器里運行一下(注意正確選擇NorthWind數據庫),就可以生成一個存儲過程:CorssTab,然后直接運行CorssTab,如果出現本文前面類似的窗格,就表示運行成功了。
d、假如用于其它表,首先需要在你的用戶數據庫里生成此存儲過程(當然也可以放到Master里,然后再加個變量:@DataBase,賦值為數據庫名稱,然后在上面代碼打開指定數據庫,這樣所有的數據庫都可以調用它),當你調用時,采取以下格式:
CorssTab @strTabName = 'Orders', @strCol = 'DATEPART(yy, OrderDate)',@strGroup = 'CustomerID', @strNumber = 'OrderID', @strSum = 'Count'
上面這條語句統計了NorthWind中Orders表里每個客戶年度訂單數量,大家可以運行試一下效果,雖然列頭顯示的名稱不恰當,但基本效果出來了,相信大家通過對我的代碼再作簡單修改,可以達到滿意的交叉表效果。
總結
以上是生活随笔為你收集整理的java动态交叉表,SqlServer如何生成动态交叉表查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA自学路线
- 下一篇: css中正确设置微软雅黑字体