2014-01-17 2 views
2

Для начала: Я запрашиваю сервер DB2, встроенный в системный пакет IBM i из Excel 2007, с помощью «Из Microsoft Query» и прямого SQL. Это финансовая база данных.Суммирование над вычисленным полем конкатенированных строк (split acct #s)

DB структурирован таким образом, что учетная запись # разделена на 8 целых полей для фонда, деления, отдела, активности 1, активности 2, элемента 1, элемента 2 и объекта. Для того, чтобы сделать запрос результатов читаемым я сцепляюсь их со следующим кодом:

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-символьная строка (для добавления начальных нулей), затем обрезание конечных пустых пространств (от преобразования типов) и, наконец, захват правильных # разрядов для каждого с использованием right(). Это в конечном итоге составляя единый учетный #, который мы используем изо дня в день в следующем формате:

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 не найдены.

Если это правда, проблема состоит в том, что предложение 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, не похожий на псевдонимы. Я изначально использовал «потому что это то, что указало Google/MS, было решением для тех, кто не может или не хочет исправлять. – Glamador

+0

И, к сожалению, в то время как это работает в автономном SQL Script автономно, я использую для тестирования кода перед вставкой в ​​MS-запрос Excel ... он фактически не работает в Excel. Он возвращается ко мне с ошибкой «Неверное выражение столбца». – Glamador

+0

И всего через 5 минут (черт вас 5 минут редактирования) Я понял, что это вызвало функцию DIGITS(). По-видимому, в SQL-версии в MS Query этого нет, объясняя, почему мой коллега использовал код, который он сделал в первую очередь. – 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

ПРАВО (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, если эти столбцы имеют значение NULL. Это традиционно довольно редко встречается в DB2 for i, поэтому, если вы это проверите, вы можете упростить некоторые вещи для себя.

+0

К сожалению, я ограничил доступ к базе данных только для чтения. Мне бы хотелось создать представление для каждой из моих 4 таблиц транзакций, но мне придется что-то делать с объединениями или объединениями. Кроме того, спасибо за исправление таблиц в моем оригинальном посте. Как это сделать правильно? – Glamador

+0

Чтобы просмотреть изменения, внесенные в вопрос, щелкните ссылку [Edited ...] (http://stackoverflow.com/posts/21191493/revisions) над информацией редактора. – WarrenT

+0

Ваш администратор базы данных или кто бы то ни было в ИТ отвечает за базу данных, может быть готов создать такое же представление, если будет достаточно его использования. – WarrenT

Смежные вопросы