16.11.2006, 18:48 | #21 |
Member
|
Цитата:
Сообщение от Gustav
...
select sum(amount) from payTrans where... человек, знакомый с "нормальным" SQL ...
__________________
С уважением, glibs® |
|
16.11.2006, 19:47 | #22 |
Moderator
|
Цитата:
Вот, не мудрствуя, скопировал из хелпа по T-SQL кусочек примера с курсором: Код: DECLARE @au_id varchar(11), @au_fname varchar(20), @au_lname varchar(40) DECLARE authors_cursor CURSOR FOR SELECT au_id, au_fname, au_lname FROM authors WHERE state = "UT" ORDER BY au_id OPEN authors_cursor FETCH NEXT FROM authors_cursor INTO @au_id, @au_fname, @au_lname Код: ОБЪЯВЛЯЕМ наши_переменные ОБЪЯВЛЯЕМ наш_курсор КАК КУРСОР ДЛЯ SELECT... (причем SELECT - на нормальном SQL!) ОТКРЫВАЕМ наш_курсор СЧИТЫВАЕМ ОЧЕРЕДНУЮ (запись) ИЗ наш_курсор В наши_переменные А здесь что? select sum(amount) from payTrans - ВЫБИРАЕМ СУММУ(amount) ИЗ... ВЫБИРАЕМ - ИЗ, ВЫБИРАЕМ - ИЗ. Ну, ИЗ-то выбираем, а ВО ЧТО выбираем-то? Вот и возникают непонятки. По-моему, вполне обоснованные. У меня знакомство с подобного рода "проблемой" началось со встречи с примерно таким фрагментом: select count(RecId) from RAssetTable Уже к тому времени зная ответственно-почётную миссию идентификатора RecId во всей системе, мозг упорно отказывался понимать, что в этом фрагменте RecId является как бы не "самим собой", а содержит всего-навсего количество записей в конкретной таблице. Согласитесь, для "неокрепшего мозга", это немного башне-сносящая откровенность. "Мы понимаем, что мы чего-то не понимаем..." |
|
17.11.2006, 09:49 | #23 |
Участник
|
Странно, но имея довольно богатый опыт работы с T-SQL у меня лично не возникло проблем в "догонянии" что делает select count(RecId) from RAssetTable
Не помню, чтобы заморачивался. Просто если вы в T-SQL пишете PHP код:
Вот потому, наверное, и сделано так - чтобы не делать "виртуальных" динамически создающихся dataset'ов... Хотя, конечно, мне, как разработчику, жутко не хватает конструкций типа такой: PHP код:
Но, тем не менее, embedded SQL и табличные переменные X++ RULEZzz! |
|
17.11.2006, 10:13 | #24 |
MCTS
|
а если я хочу после этой конструкции обратиться не к полученной переменной, которая содержит подсчитанную сумму, а к полю записи этой таблицы (т.е. к обычному текущему курсору), тогда интересно что делать? Ведь если я пишу
RPayTrans.Amount, то это выдаст ту самую сумму по записям, с другой стороны, мне нужно обратиться к конкретной записи по полю, т.е. RPayTrans.Amount - как тогда быть? |
|
17.11.2006, 10:21 | #25 |
Злыдни
|
Сделать выборку записи, т.е. select без агрегирования
|
|
|
За это сообщение автора поблагодарили: Eldar9x (1). |
17.11.2006, 10:22 | #26 |
Программатор
|
|
|
|
За это сообщение автора поблагодарили: Eldar9x (1). |
17.11.2006, 10:28 | #27 |
Moderator
|
Eldar9x, рекомендую еще обратить внимание на мою тему Прикольная конструкция: оператор select с полем (она также внизу болтается в "Похожих темах" к этой теме). Думаю, Вам понравится.
|
|
17.11.2006, 12:22 | #28 |
Moderator
|
небольшой офф-топик про WITH
Цитата:
Хлебнув чуть больше года назад в Oracle 9.2 SQL-счастье под названием "фраза WITH с подзапросом" (subquery factoring clause), я уже с трудом понимаю, как можно возвращаться в такой каменный век SQL, где этого нет. Чесслово, говорю это не пижонства или красного словца ради. Несмотря на то, что синтаксис ANSI-шный, Microsoft, к сожалению, вроде не торопится прикручивать эту фичу к SQL Server (или может сделали уже?!) А вот обладатели Oracle 9.2 и выше, кто еще не в курсе, рекомендую обратить на этот WITH пристальное внимание. В качестве примера привожу один свой рабочий запрос. Этот запрос выбирает неамортизируемые карточки основных средств в некоторой модели учета ОС ('GAAP') на определенную дату. Вникать в его бизнес-суть абсолютно необязательно. Это просто иллюстрация того, как подзапросы могут взаимодействовать между собой и как можно эффективно структурировать сложные запросы (практически в этаком "последовательно-процедурном" стиле, невиданном доселе для SELECT'ов): Код: SELECT * FROM ( WITH -- ЗДЕСЬ Я ОПРЕДЕЛЯЮ НЕСКОЛЬКО ИМЕНОВАННЫХ ПОДЗАПРОСОВ (имена "подчеркнуты") ------------------ RATrans AS ------------------ (SELECT accountnum, MIN(CASE WHEN assettranstype = 3 THEN transdate END) acq_transdate, SUM(CASE WHEN assettranstype = 0 THEN amountmst ELSE 0 END) amt_0, SUM(CASE WHEN assettranstype = 2 THEN amountmst ELSE 0 END) amt_2, SUM(CASE WHEN assettranstype = 3 THEN amountmst ELSE 0 END) amt_3, SUM(CASE WHEN assettranstype = 4 THEN amountmst ELSE 0 END) amt_4, SUM(CASE WHEN assettranstype = 5 THEN amountmst ELSE 0 END) amt_5, SUM(CASE WHEN assettranstype = 7 THEN amountmst ELSE 0 END) amt_7, SUM(CASE WHEN assettranstype = 15 THEN amountmst ELSE 0 END) amt_15, SUM(CASE WHEN assettranstype = 16 THEN amountmst ELSE 0 END) amt_16, SUM(CASE WHEN assettranstype NOT IN (0,2,3,4,5,7,15,16) THEN amountmst ELSE 0 END) amt_other FROM RASSETTRANS WHERE assetstandardid = 'GAAP' AND transdate <= TO_DATE('30.09.2006', 'DD.MM.YYYY') GROUP BY accountnum ), ------------------------ HavingAmort AS ------------------------ (SELECT accountnum FROM RASSETTRANS WHERE assettranstype = 0 AND assetstandardid = 'GAAP' AND transdate <= TO_DATE('30.09.2006', 'DD.MM.YYYY') ), ---------------------------- NoHavingAmort AS ---------------------------- (SELECT ratable.accountnum AS accountnum FROM RASSETTABLE ratable, HavingAmort ratrans -- <-- ИСПОЛЬЗУЕМ РАНЕЕ (выше) ОПРЕДЕЛЕННЫЙ ПОДЗАПРОС HavingAmort "как простую таблицу" - неплохо, правда? :-) WHERE ratable.accountnum = ratrans.accountnum(+) AND ratrans.accountnum IS NULL ), ------------------------------- NecessaryAssets AS ------------------------------- -- карточки, не имеющие амортизации в западном учете (когда либо до даты) (SELECT accountnum FROM NoHavingAmort -- -- ОПЯТЬ ИСПОЛЬЗУЕМ РАНЕЕ (выше) ОПРЕДЕЛЕННЫЙ ПОДЗАПРОС NoHavingAmort "как простую таблицу", который в свою очередь - см. выше тоже включает подзапрос HavingAmort, т.е. уже пошла вложенность, сносящая башню при неиспользовании фразы WITH :-) UNION -- карточки, у которых нет амортизации (отключена) SELECT assetid FROM RASSETSTANDARDS WHERE depreciation = 0 AND assetstandardid = 'GAAP' UNION -- карточки, имеющие ост. стоимость <= 0, но не выбывшие ---------------------------------------------- SELECT accountnum FROM ( SELECT accountnum, (amt_2 + amt_3 + amt_4 + amt_16) AS PS, -(amt_0) AS Amort FROM RATrans WHERE ROUND(amt_5,2) = 0 AND ROUND(amt_7,2) = 0 ) WHERE ROUND(PS,2) <= ROUND(Amort,2) ) -- -- СОБСТВЕННО НАЧИНАЕТСЯ ОСНОВНОЙ СЕЛЕКТ (самый внешний "SELECT * FROM ( WITH ...)" основным не считаем - это обертка для TOAD ) SELECT ratable.accountnum AS "Asset Code", ratable.dataareaid AS "Company", ratable.status AS "Status Value", en.en_label AS "Status Label", stand.depreciation AS "Depr Turn ON", neverb4.never_b4 AS "Never Before", -- CASE WHEN ratable.status <> 7 THEN NVL((trans.amt_2 + trans.amt_3 + trans.amt_4 + trans.amt_16), 0) ELSE NVL((trans.amt_2 + trans.amt_3 + trans.amt_4 + trans.amt_16), 0) + NVL(stand.acquisitionprice, 0) END AS "IC", -- -NVL(trans.amt_0, 0) AS "Depr", -- CASE WHEN ratable.status <> 7 THEN NVL((trans.amt_2 + trans.amt_3 + trans.amt_4 + trans.amt_16)+ (trans.amt_0), 0) ELSE NVL((trans.amt_2 + trans.amt_3 + trans.amt_4 + trans.amt_16)+ (trans.amt_0), 0) + NVL(stand.acquisitionprice, 0) END AS "Net", -- trans. acq_transdate AS "Acq.Date (GAAP, RATrans)", ratable.acquisitiondate AS "Acq.Date (RATable)", ratable.acquisitionprice AS "Acq.Price (RATable)", stand.acquisitionprice AS "Acq.Price (RAStand)", trans.amt_0 AS "Amt_0_Depreciation", trans.amt_2 AS "Amt_2_Revaluation", trans.amt_3 AS "Amt_3_Acquisition", trans.amt_4 AS "Amt_4_AcquisitionAdj", trans.amt_5 AS "Amt_5_DisposalSale", trans.amt_7 AS "Amt_7_Disposal", trans.amt_15 AS "Amt_15_Investment", trans.amt_16 AS "Amt_16_InvestmentOpen", amt_other AS "Amt_Other_AssetTransTypes" -- FROM -- RATrans trans, -- <-- ИСПОЛЬЗУЕМ ИМЕННОВАННЫЙ ПОДЗАПРОС из зоны WITH -- (SELECT assetid, acquisitionprice, depreciation FROM RASSETSTANDARDS WHERE assetstandardid = 'GAAP' ) stand, -- -- ДЛЯ ИНДИКАЦИИ: карточки, не имеющие амортизации в западном учете (когда либо до даты) (SELECT accountnum, 'Never' AS never_b4 FROM NoHavingAmort -- <-- ИСПОЛЬЗУЕМ ИМЕННОВАННЫЙ ПОДЗАПРОС из зоны WITH ) neverb4, -- -- расшифровка значений статуса (SELECT * FROM AX_BASE_ENUMS WHERE en_type = 'RAssetStatus') en, -- (SELECT accountnum, dataareaid, status, acquisitiondate, acquisitionprice FROM RASSETTABLE ) ratable, -- NecessaryAssets nassets -- <-- ИСПОЛЬЗУЕМ ИМЕННОВАННЫЙ ПОДЗАПРОС из зоны WITH -- WHERE nassets.accountnum = ratable.accountnum -- здесь без (+) !!! AND ratable.status = en.en_value(+) AND ratable.accountnum = neverb4.accountnum(+) AND ratable.accountnum = stand.assetid(+) AND ratable.accountnum = trans.accountnum(+) ) ORDER BY 1 Код: CREATE TABLE AX_BASE_ENUMS ( EN_TYPE VARCHAR2(100 BYTE) NOT NULL, EN_VALUE NUMBER(10) NOT NULL, EN_LABEL VARCHAR2(200 BYTE) NOT NULL, EN_ELEMENT VARCHAR2(100 BYTE) ) |
|
31.01.2007, 19:07 | #29 |
Участник
|
Добрый вечер!
У меня есть название поля в таблице считай "amount", т.е : fieldId = fieldName2Id(tableNum(RPayTrans), "amount"); RPayTrans.(fieldId); Как мне к нему обратится, в конструкции "Select sum() from"? |
|
01.02.2007, 14:03 | #30 |
Участник
|
Можно так:
X++: Query q = new Query(''); QueryBuildDatSource ds; ; ds = q.addDataSource(TableNum(RPayTrans)); ds.addSelectiontField(fieldName2Id(tableNum(RPayTrans), "amount"), SelectionField::Sum); |
|
01.02.2007, 15:41 | #31 |
Участник
|
|
|
01.02.2007, 16:10 | #32 |
Участник
|
Трудно сказать. Правильнее наверное было бы не передавать. То ли в предыдущих версиях аксапты этот параметр был обязательным, то ли у предыдущего программиста были свои сообращения на этот счет. Но факт остается фактом - данная конструкция благодаря буферу обмена расплодилась по всему коду приложения.
|
|
01.02.2007, 16:20 | #33 |
злыдень
|
УжОс! Многа букв.
И слава богу что нет.. Я одного не понимаю чем этот изврат, которого нет, лучше хранимок и триггеров которые везде есть уже n десятков лет ??? Неужели программировать в родном "последовательно-процедурном" стиле не приятнее на порядок??? Вот как выглядит типичная обработка на firebird, по моему все понятно без слов: Код: AS declare variable znak integer; declare variable sumnds double precision; BEGIN IF (NEW.ID IS NULL) THEN NEW.ID = GEN_ID(GEN_Z_PROVODKA_ID,1); /* Перед подстановкой в основную считаем параметры осн записи и рассчитаем себестоимость*/ if (new.id_pribyl<>0) then /* Прибыли */ begin select first 1 data, skladkod, statuskod, celkod from Z_PRIBYL where Z_PRIBYL.id = NEW.id_pribyl into new.data, new.skladprihod, new.status, new.typeoper; select result from f_valuta_calc(new.summaval,new.data,new.valutakod) into new.summaprihod; new.summaoper = new.summaprihod; end if (new.id_ubytok<>0) then/* Убытки */ begin select first 1 data, skladkod, statuskod, celkod from Z_UBYTOK where Z_UBYTOK.id = NEW.id_ubytok into new.data, new.skladrashod, new.status, new.typeoper; select result from z_ostatok_stoim(new.status,new.tovarkod,new.skladrashod,new.kolnov * (-1)) into new.summarashod; new.summaoper = new.summarashod; end if (new.id_perem <> 0) then /*Перемещения*/ begin select first 1 dataprih, datarash, skladrashodkod, skladprihodkod, statuskod, celkod from Z_PEREM where Z_PEREM.id = new.id_perem into new.data,new.datarashod, new.skladrashod, new.skladprihod, new.status, new.typeoper; select result from z_ostatok_stoim(new.status,new.tovarkod,new.skladrashod,new.kolnov * (-1)) into new.summarashod; new.summaprihod = (-1)*new.summarashod; new.summaoper = new.summarashod; end if (new.id_zpnakl <> 0) then /* Закупка */ begin select first 1 data, skladkod, statuskod, celkod, postkod, valutakod from zp_nakl where zp_nakl.id = NEW.id_zpnakl into new.data, new.skladprihod, new.status, new.typeoper, new.postkod, new.valutakod; select result from f_valuta_calc((new.summaval-new.summands),new.data,new.valutakod) into new.summaprihod; UPDATE ZP_NAKL SET SUMMA = SUMMA + new.summaprihod WHERE (ID = new.id_zpnakl); select result from f_valuta_calc(new.summands,new.data,new.valutakod) into new.summaoper; UPDATE ZP_NAKL SET SUMMANDS = SUMMANDS + new.summaoper WHERE (ID = new.id_zpnakl); new.summaoper = new.summaprihod; end if (new.id_prnakl <> 0) then /* Продажа */ begin select first 1 data, skladkod, statuskod, celkod, klientkod, valutakod from pr_nakl where pr_nakl.id = NEW.id_prnakl into new.data, new.skladrashod, new.status, new.typeoper, new.klientkod, new.valutakod; select result from f_valuta_calc(new.summaval-new.summands,new.data,new.valutakod) into new.summaoper; select result from z_ostatok_stoim(new.status,new.tovarkod,new.skladrashod,new.kolnov * (-1)) into new.summarashod; select result from f_valuta_calc(new.summands,new.data,new.valutakod) into sumnds; UPDATE PR_NAKL SET SUMMA = SUMMA + new.summaoper, SUMMANDS = SUMMANDS + :sumnds WHERE (ID = new.id_prnakl); end if (new.kolnov = 0) then exit; /* Контроль */ if ((new.tovarkod is null) or (new.skladprihod is null AND new.skladrashod is null)) then execute procedure ERROR('Проводки в никуда быть не может'); /* Собственно тригер */ /* Приход:"+", Расход:"-" */ if (new.status > 0) then znak = 1; else znak = (-1); /*Возвраты*/ if (not (new.skladprihod is null)) then begin new.kolprihod = new.kolnov; execute procedure z_ostatok_calc (new.tovarkod,new.skladprihod,new.kolprihod,new.summaprihod,:znak,new.status); end if (not (new.skladrashod is null)) then begin new.kolrashod = new.kolnov*(-1); execute procedure z_ostatok_calc (new.tovarkod,new.skladrashod,new.kolrashod,new.summarashod,:znak,new.status); end /* Обновим статусы*/ if (new.status = 1) then new.ZAAVKA = new.kolnov; else if (new.status = 2) then new.ZAKAZ = new.kolnov; else if (new.status = 3) then new.REZERV = new.kolnov; else if (new.status = 4) then new.PUT = new.kolnov; else if (new.status = 5) then new.ZAVER6ENO = new.kolnov; END
__________________
Ибо зло есть лучшая сила человека. "Человек должен становиться все лучше и злее" -- так учу я. /Ф. Ницше/ |
|
01.02.2007, 16:41 | #34 |
Участник
|
А еще CTE (они, кстати, появились в MS SQL 2005) можно определять рекурсивно:
Код: WITH DirectReports(ManagerID, EmployeeID, EmployeeLevel) AS ( SELECT ManagerID, EmployeeID, 0 AS EmployeeLevel FROM HumanResources.Employee WHERE ManagerID IS NULL UNION ALL SELECT e.ManagerID, e.EmployeeID, EmployeeLevel + 1 FROM HumanResources.Employee e INNER JOIN DirectReports d ON e.ManagerID = d.EmployeeID ) SELECT ManagerID, EmployeeID, EmployeeLevel FROM DirectReports ; Последний раз редактировалось belugin; 01.02.2007 в 16:43. |
|
Теги |
amount, запрос (query), как правильно |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|