2014-01-17 38 views
2

開始:我使用「From Microsoft Query」和直接SQL查詢從Excel 2007內置到IBM i System包中的DB2服務器。這是一個金融數據庫。總結連接字符串的計算字段(分割acct #s)

該數據庫的結構使帳戶#分成基金,部門,部門,活動1,活動2,元素1,元素2和對象8個整數字段。爲了使查詢結果可讀性我已經級聯他們用下面的代碼:

select 
    right(trim(trailing from (concat('00',cast(T1."GMFUND" as Char(8))))),3)||'-' 
||right(trim(trailing from (concat('00',cast(t1."GMDPT" as Char(8))))),2) 
||right(trim(trailing from (concat('00',cast(T1."GMDIV" as Char(8))))),2) ||'-' 
||right(trim(trailing from (concat('00',cast(T1."GMSTAB" as Char(8))))),2) 
||right(trim(trailing from (concat('00',cast(T1."GMSTAS" as Char(8))))),1)||'.' 
||right(trim(trailing from (concat('00',cast(T1."GMELM1" as Char(8))))),1) 
||right(trim(trailing from (concat('00',cast(T1."GMELM2" as Char(8))))),1)||'-' 
||right(trim(trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2) 
    as AJAccount 

這是一個有點難以閱讀,所以我會解釋一下:對於每一個領域,我串聯「00」,以強制轉換爲每個#一個8字符的字符串(用於添加前導零),然後修剪尾部空格(來自類型轉換),最後爲每個使用權利()獲取正確的位數。這最終彌補我們用一天到一天在以下格式的ACCT#:

000-0000-000.00-00

現在,這裏是更復雜的部分。我需要計算借方和貸方的計算字段,其定義如下:

IFNULL(T1."GMDAMT",0)-IFNULL(T1."GMCAMT",0) as Trans_Total 

但是這還沒有總結。這就是我遇到我的問題的地方。當我查詢這兩個字段時,我會得到數據庫中每個事務的準確結果,標記爲w/acct #s。但是,當我嘗試將[debits - credits]字段放在SUM()聚合函數中並通過'AJAccount'組進行分組時,我的查詢會引發錯誤。

錯誤指向我的級聯ACCT#字段的以下部分:

right(trim (trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2) 

具體來說它突出「GMOBJ」爲錯誤的來源。但是,如果沒有SUM()函數,代碼運行良好,生產的結果如下所示:

001-0000-243.00-00 | 166898.00 
001-0000-244.00-00 | -166898.00  
161-0000-243.00-00 | 3000.00  
161-0000-244.00-00 | -3000.00  
470-0000-243.00-00 | 4999.00  
470-0000-244.00-00 | -4999.00  
490-0000-243.00-00 | 1000.00  
490-0000-244.00-00 | -1000.00 

,這不算什麼,我真正需要做的(因爲交易數據被分割一半按交易類型分成4個不同的表格,我最終需要加入......但這是另一項任務)。但是,直到我得到這個工作,我在一個停止。

這是整個代碼塊:

select 
    right(trim(trailing from (concat('00',cast(T1."GMFUND" as Char(8))))),3)||'-' 
    ||right(trim(trailing from (concat('00',cast(t1."GMDPT" as Char(8))))),2) 
    ||right(trim(trailing from (concat('00',cast(T1."GMDIV" as Char(8))))),2) ||'-' 
    ||right(trim(trailing from (concat('00',cast(T1."GMSTAB" as Char(8))))),2) 
    ||right(trim(trailing from (concat('00',cast(T1."GMSTAS" as Char(8))))),1)||'.' 
    ||right(trim(trailing from (concat('00',cast(T1."GMELM1" as Char(8))))),1) 
    ||right(trim(trailing from (concat('00',cast(T1."GMELM2" as Char(8))))),1)||'-' 
    ||right(trim(trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2) 
     as AJAccount, 
    SUM(IFNULL(T1."GMDAMT",0)-IFNULL(T1."GMCAMT",0)) as Trans_Total 
from "HTEDTA"."GM310AP" T1 
where T1."GMAPYR" = 2014 
group by 'AJAccount' 

我想也許我typo'd什麼的,所以我做了以下比較容易查詢:

select 
T1."GMFUND", 
SUM(IFNULL(T1."GMDAMT",0)-IFNULL(T1."GMCAMT",0)) as Trans_Total 
from "HTEDTA"."GM310AP" T1 
where T1."GMAPYR" = 2014 and T1."GMAPMO" between 1 and 4 
group by T1."GMFUND" 
order by T1."GMFUND" 

,它跑了就好了,產生以下結果:

1 | 20090901.49 
111 |  32635.15 
114 |   0.00 
115 |   0.00 
131 |  5916.66 

所以我懷疑我缺乏有關計算字段和SUM ()。有人能夠啓發我嗎?

+0

出於好奇,你爲什麼決定'CHAR'格式而不是'INT(8)'? – Sev09

+1

因爲RIGHT()函數需要一個字符串輸入,而INT類型無論如何都不會保留前導零。一位同事寫道,爲了自己的使用並允許我使用它,我認爲他使用了最有效的方法。 – Glamador

+0

感謝您的回答。你是對的前導零。 – Sev09

回答

2

假設錯誤是SQL0206 - 未找到列或全局變量AJAccount。

如果爲true,問題是GROUP BY子句正在查找數據庫表中的列,而不是SELECT子句中的派生列。嘗試把整個派生列在GROUP BY:

select... 
where... 
group by right(trim (trailing from (concat('00',cast(T1."GMFUND" as Char(8))))),3) || '-' || right(trim (trailing from (concat('00',cast(t1."GMDPT" as Char(8))))),2) || right(trim (trailing from (concat('00',cast(T1."GMDIV" as Char(8))))),2) || '-' || right(trim (trailing from (concat('00',cast(T1."GMSTAB" as Char(8))))),2) || right(trim (trailing from (concat('00',cast(T1."GMSTAS" as Char(8))))),1) || '.' || right(trim (trailing from (concat('00',cast(T1."GMELM1" as Char(8))))),1) || 
right(trim (trailing from (concat('00',cast(T1."GMELM2" as Char(8))))),1) || '-' || right(trim (trailing from (concat('00',cast(T1."GMOBJ" as Char(8))))),2) 
order by 1 
+0

我感謝所有人的回覆,他們都幫助我們縮短了代碼的使用時間,並且更加輕鬆。但只有這個解決方案實際上解決了GROUP BY問題。我認爲這與最新版本的MS Office Query不喜歡別名有關。我最初使用'因爲這是谷歌/微軟表示是那些不能或不願意補丁的解決方案。 – Glamador

+0

不幸的是,雖然這可以在獨立的SQL腳本中獨立運行,但在粘貼到Excel的MS Query之前,我使用它來測試代碼......它實際上並不在Excel中工作。它以「錯誤的列表達式」錯誤回到了我的面前。 – Glamador

+0

而僅僅5分鐘後(讓你5分鐘的編輯限制)我發現它是導致它的「DIGITS()」函數。顯然MS Query中的SQL版本沒有這個功能,解釋了爲什麼我的同事首先使用了他所做的代碼。 – Glamador

2

一個簡單的例子使用common-table-expression

WITH gm310ap AS (SELECT 
    RIGHT('00'||DIGITS(gmfund),3) || '-' || 
    RIGHT('0'||DIGITS(gmdpt),2) || 
    RIGHT('0'||DIGITS(gmdiv),2) || '-' || 
    RIGHT('0'||DIGITS(gmstab),2) || 
    RIGHT(DIGITS(gmstas),1) || '.' || 
    RIGHT(DIGITS(gmelm1),1) || 
    RIGHT(DIGITS(gmelm2),1) || '-' || 
    RIGHT('0'||DIGITS(gmobj),2) AS AJAccount, 
    COALESCE(gmdamt,0) - COALESCE(gmcamt,0) AS Trans_Total 
FROM "HTEDTA"."GM310AP" 
WHERE gmapyr = 2014) 
SELECT AJAccount, SUM(Trans_Total) 
FROM gm310ap 
GROUP BY AJAccount 

文檔中的標量函數:

+1

RIGHT(DIGITS())會更簡單和更快,呃? – WarrenT

+0

@WarrenT你是對的。我更新了答案以顯示簡化的方法。零填充可能是不必要的,但我們不知道原始字段是如何定義的。 – jamesallman

+0

如果gmfund只被定義爲2位,那麼你可以說''0'|| digits(gmfund)'。 – WarrenT

0

如果顯示的代碼是你跑什麼,那麼你的查詢有一個簡單的語法問題。你說GROUP BY 'AJAccount'這是一個字符串文字。雙引號("AJAccount")將使其成爲區分大小寫的列引用。但是,如果您說as AJAaccount您沒有使用雙引號,則名稱不區分大小寫,因此您不需要GROUP BY中的引號。

假設你列至少只要你想提取的部分,我會嘗試以下查詢:

SELECT ( RIGHT(DIGITS(gmfund),3) ||'-' 
     || RIGHT(DIGITS(gmdpt),2) 
     || RIGHT(DIGITS(gmdiv),2) || '-' 
     || RIGHT(DIGITS(gmstab),2) 
     || RIGHT(DIGITS(gmstas),1) || '.' 
     || RIGHT(DIGITS(gmelm1),1) 
     || RIGHT(DIGITS(gmelm2),1) || '-' 
     || RIGHT('0'||DIGITS(gmobj),2) 
     ) as AJAccount, 
     sum(gmdamt) - sum(gmcamt) AS Trans_Total 
    FROM "HTEDTA"."GM310AP" 
    WHERE gmapyr = 2014 
    GROUP BY AJAccount 

我的猜測是,可能有很多會使用這種其他查詢連接的帳號。一旦已創建

CREATE OR REPLACE VIEW HTEDTA.GM310AP_AC 
    SELECT ( RIGHT(DIGITS(gmfund),3) ||'-' 
     || RIGHT(DIGITS(gmdpt),2) 
     || RIGHT(DIGITS(gmdiv),2) || '-' 
     || RIGHT(DIGITS(gmstab),2) 
     || RIGHT(DIGITS(gmstas),1) || '.' 
     || RIGHT(DIGITS(gmelm1),1) 
     || RIGHT(DIGITS(gmelm2),1) || '-' 
     || RIGHT('0'||DIGITS(gmobj),2) 
     ) as AJAccount, 
     gmdamt, 
     gmcamt  -- include any other useful columns 
    FROM HTEDTA.GM310AP 

,你可以寫的查詢,如

SELECT AJAccount, 
     SUM(IFNULL(gmdamt,0) - IFNULL(gmcamt)) as Trans_Total 
    FROM HTEDTA.GM310AP_AC 
    GROUP BY AJAccount 
    ORDER BY AJAccount 

:如果是這樣的話,你可以考慮創建一個視圖來存儲別處這個邏輯使用,也許這樣的或者

WITH Q AS 
(SELECT AJAccount, 
     SUM(gmdamt) as TotD, 
     SUM(gmcamt) as TotC 
    FROM HTEDTA.GM310AP_AC 
    GROUP BY AJAccount 
) 
SELECT AJAccount, 
     TotD - TotC as Trans_Total 
    FROM Q 
    ORDER BY AJAccount 

PS如果這些列可以爲空,則只需要IFNULL。對於DB2來說,這在傳統上很少見,因此如果您檢查了這一點,您可能會爲自己簡化一些事情。

+0

不幸的是,我只能以只讀方式訪問數據庫。我希望爲我的每個4個交易表創建一個視圖,但我將不得不對聯合或似乎做一些工作。另外,感謝您在原始文章中修復表格。如何正確地做到這一點? – Glamador

+0

要查看對問題所做的編輯,請單擊編輯器信息上方的[編輯...](http://stackoverflow.com/posts/21191493/revisions)鏈接。 – WarrenT

+0

您的DBA或IT部門負責數據庫的人可能願意創建一個類似的視圖,只要能夠充分利用它即可。 – WarrenT