![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Объект по работе с cross-таблицей
DelphiLexx © (2007-03-21 15:20:00)Возникла следующая проблема:
Есть таблица Q_DICT со следующей структорой:
QM_ID QM_NAME DESCRIPTION
см рис pic1.
Есть таблица R_DICT (аналог Q_DICT)
R_ID R_NAME DESCRIPTION
см рис pic2
Есть Таблица RQ_DICT состоящая из данных Q_DICT и R_DICT
R_ID Q_ID RQ_VALUE
где R_ID, Q_ID внешние ключи на ID - полей на таблицы на Q_DICT R_DICT
см рис pic3
Нужен объект которому бы я передавал список R_ID, QM_ID и он бы мне возвращал скажем TRxMemoryData следующей структуры
см рис pic_4
http://www.rsdn.ru:80/File/26841/pic_itog.JPG
DelphiLexx (2007-05-21 16:56:00) [1]
> <a href= ></a> [url=][/url]
Что это за бред.
zklxm (2007-05-19 18:47:00) [2]<a href= ></a> [url=][/url]
gizfi (2007-05-19 09:16:00) [3]<a href= ></a> [url=][/url]
DelphiLexx (2007-03-27 17:24:00) [4]
> SelectSQL и перед выполнением запроса поставить в нем свойство
> ParamCheck = false.
тогда переменные Returns понимаются, а передаваемые параметры после ParamCheck := false не понимаются. Если сделать так ParamCheck := true, то становиться все наоборот.
Jan (2007-03-22 09:57:00) [5]
> Для тебя это так принципиально ? :))
чистота кода - это тоже хороший совет, не находишь?
> Причем, он не работоспособный на 100%, там есть несколько
> ошибок.
т.е. ты предлагаешь его мне копировать себе и разбираться - увольте. автору надо - пусть поломает голову.
PEAKTOP (2007-03-22 09:49:00) [6]
> я давно такого не читал где бы весь код был в коде нажатия кнопки...
Для тебя это так принципиально ? :))
Код, приведенный выше - изложение самой идеи и написан для примера. Причем, он не работоспособный на 100%, там есть несколько ошибок. Если у автора топика получилось выполнить полученный в результате запрос в IBExpert-e, то значит он нашел эти ошибки и исправил.
Как ни странно, ты на них не указал, кроме принципиальных кнопок.
PEAKTOP (2007-03-22 09:38:00) [7]
> Это как раз место где между R_DICT TB INTO и :R_ID
FIBPlus досконально не знаю (так, кодил пару раз), потому как пользую самописную библиотеку доступа, основанную на исходниках IBX. Но в любом случае, копать тебе нужно в сторону проверки параметров перед выполнением запроса. В IBX это свойство TIBQuery.ParamCheck :Boolean, его нужно поставить в false, чтобы парсер не проверял параметры перед выполнением запроса.
Проблема заключается в том, что "двоеточие" и "вопросительный знак" в компонентах Delphi зарезервировано под параметры, а в Procedure SQL двоеточие тоже зарезервировано под передачу значений в параметры хранимой процедуры, поэтому парсер "путается" перед выполнением запроса не отличая, где параметры, а где передача значений. Как сказано в фирменной документации ($firebird/doc/sql.extensions/README.execute_block.txt)
....................
The client should preprocess only head of the SQL statement or use '?'
instead of ':' as parameter indicator because in a body of the block may be links
to local variables and \ or parameters with a colon ahead.
...........................
(c) Vlad Horsun <horsun@kdb.dp.ua>
Я проблему решил тем, что перекрыл в исходниках те места, где парсится SQL, оставив для передачи параметров только "вопросительный знак" и убил "двоеточие".
В твоем случае можно попробовать следующее.
Компонент T..DataSet из набора FIBPlus имеет пять скрытых компонентов TSQL, свойства SQL которых вынесены в published как SelectSQL, InsertSQL, DeleteSQL и т.д. Тебе нужно найти компонент ( T..DataSet.FindComponent('CompName') ), который SelectSQL и перед выполнением запроса поставить в нем свойство ParamCheck = false.
Jan (2007-03-22 09:34:00) [8]
> Помогаем сайту зарабатывать кровные 395$ ? :))
чуть Выше я предлагал заюзать бесплатные, но автор не понимает что ему нужно, а по программировании извини, я давно такого не читал где бы весь код был в коде нажатия кнопки...
>
> Это как раз место где между R_DICT TB INTO и :R_ID
символ : не начто не наводит? Ты бы почитал чтоли хелп, прежде чем юзать компоненты...
DelphiLexx (2007-03-21 20:21:00) [9]
> Этап первый - пробуем:
> 1) Читаем какую-нить книжку по созданию хранимых процедур
> в InterBase/FireBird
Я использую компоненты FIBPlus'a написал В DataSet.Seletct.Sql готовый execute block. Проверил его в IBExpert'e замечательно работает, но когда начинаю его выполнять из программы выдается ошибка
Token unknown line 1 column 248
?.
Это как раз место где между R_DICT TB INTO и :R_ID
PEAKTOP (2007-03-21 19:22:00) [10]
> по коду не будем - Вам бы почитать вообще о программировании.
Не поверишь, каждый день читаю и при этом черпаю что-то новое. Однако при этом болезненное самомнение как-то не развивается, а скроее наоборот.
> а в общем, зачем изобретать велик - если уже все сделали за нас? только поискать...
Программирование со времен фон Неймана - сплошное изобретание велика.
> хотя бы это
> http://pivotcube.com/cgi-bin/index.cgi?page=products
Помогаем сайту зарабатывать кровные 395$ ? :))
Jan (2007-03-21 19:00:00) [11]хотя бы это
http://pivotcube.com/cgi-bin/index.cgi?page=products
Jan (2007-03-21 18:57:00) [12]
> PEAKTOP © (21.03.07 17:52) [15]
по коду не будем - Вам бы почитать вообще о программировании.
а в общем, зачем изобретать велик - если уже все сделали за нас? только поискать...
PEAKTOP (2007-03-21 18:03:00) [13]
> Jeer © (21.03.07 16:50) [14]
>
> Для примера можно ее делать так:
Хм, неплохая идея ! спасибо.
PEAKTOP (2007-03-21 17:52:00) [14]
> только ты сначала расскажи как вернуть динамическое кол-во столбцов, а потом рекомендуй...
Этап первый - пробуем:
1) Читаем какую-нить книжку по созданию хранимых процедур в InterBase/FireBird.
2) Пишем хранимую процедуру (для сферического коня в вакууме).
3) Заменяем в ней "CREATE PROCEDURE PROC_NAME" на "EXECUTE BLOCK".
4) Засовываем в свойство TIBQuery.SQL.Text := полученный скрипт.
Этап второй - усложняем (на примере автора топика, если позволите):
Допустим, у нас на форме Form1 лежит dbg:TDBGridEh, изображенный на PICT_4для него набор данных qr:TIBQuery; (Свойство ParamCheck = false - это важно для IBX !!!)
Также есть IBQuery1 :TIBQuery вспомагательный
procedure TForm1.Button1Click(Sender :TObject);
var
lk_Vars, lk_Body, lk_SQL :string;
lk_Col :TColumnEh;
i :Integer;
begin
if IBQuery1.Active then IBQuery1.Close;
dbg.Columns.Clear;
lk_Col := dbg.Columns.Add;
lk_col.FieldName := 'R_NAME';
lk_Col.Title.Caption := 'R_NAME';
.... и т.д. выставляем свой-ва первой колонки.
IBQuery1.SQL.Text := 'SELECT * FROM Q_DICT ORDER BY QM_ID ';
IBQuery1.Open;
IBQuery1.First;
lk_vars := '';
lk_body := '';
i := 0;
while not IBQuery1.EOF do
begin
lk_Vars := lk_Vars +#13#10+' ,FLD'+IntToStr(i)+' NUMERIC(15,2) ';
lk_body := lk_body +#13#10+' SELECT FIRST 1 T.RQ_VALUE FROM RQ_DICT T WHERE (T.R_ID = :R_ID) and (T.Q_ID = '''+IBQuery1.FieldByName('QM_ID').AsString+''') INTO :FLD'+IntToStr(i)+'; ';
lk_Col := dbg.Columns.Add;
lk_col.FieldName := 'FLD'+IntToStr(i);
lk_Col.Title.Caption := IBQuery1.FieldByName('QM_NAME').AsString;
.... и т.д. выставляем свой-ва колонки.
i := i + 1;
IBQuery1.Next;
end;
if qr.Active then qr.Close;
qr.SQL.Text :=
'EXECUTE BLOCK RETURNS ( '+#13#10+
' R_ID INTEGER '+#13#10+
' ,R_NAME VARCHAR(50) '+#13#10+
lk_vars+#13#10+
') AS '+#13#10+
'BEGIN '+#13#10+
' FOR SELECT TB.R_ID, TB.R_NAME FROM R_DICT TB INTO :R_ID, :R_NAME DO '+#13#10+
' BEGIN '+#13#10+
lk_body+#13#10+
' SUSPEND; '+#13#10+
' END'+#13#10+
'END ';
end;
Jeer (2007-03-21 16:50:00) [15]Ищи по ключ.словам: cross-таблица, перекрестная таблица, шахматка.
Для примера можно ее делать так:
CREATE TABLE Pivot
( Year SMALLINT,
Quarter TINYINT,
Amount DECIMAL(2,1) )
SELECT Year,
SUM(CASE Quarter WHEN 1 THEN Amount ELSE 0 END) AS Q1,
SUM(CASE Quarter WHEN 2 THEN Amount ELSE 0 END) AS Q2,
SUM(CASE Quarter WHEN 3 THEN Amount ELSE 0 END) AS Q3,
SUM(CASE Quarter WHEN 4 THEN Amount ELSE 0 END) AS Q4
FROM Pivot
GROUP BY Year
DelphiLexx (2007-03-21 16:40:00) [16]
> тебе нужен OLAP.
что такое OLAP
Jan (2007-03-21 16:29:00) [17]
> Формируй набор данных через динамическую хранимую процедуру
> EXECUTE BLOCK, а само тело процедуры (и заодно отчет, ну
> там метки раскидывай по бэндам) формируй программно в цикле
> по справочнику, по которому хочешь "развернуть горизонтально".
>
> Только на IBX забей сразу с этими приколами. Воcпользуйся
> FIBPlus.
только ты сначала расскажи как вернуть динамическое кол-во столбцов, а потом рекомендуй...
> Что касается Pivot таблиц, по-моему, немного не то.
как раз-то. тебе нужен OLAP.
DelphiLexx (2007-03-21 16:27:00) [18]
> Формируй набор данных через динамическую хранимую процедуру
> EXECUTE BLOCK, а само тело процедуры (и заодно отчет, ну
> там метки раскидывай по бэндам) формируй программно в цикле
> по справочнику, по которому хочешь "развернуть горизонтально".
>
EXECUTE BLOCK - а как этой процедурой пользоваться. И разве такое возможно, чтобы часть хранимой процедуры была в БД Firebird, а часть в проекте.
Не мог бы напримере рассказать как это делается.
DelphiLexx (2007-03-21 16:24:00) [19]
> http://delphikingdom.ru/asp/viewitem.asp?catalogid=529
Дело в том, что я использую EhLib поэтому переходить но новый грид желания нет. Хотелось бы просто найти объект а не компонент.
Что касается Pivot таблиц, по-моему, немного не то.
PEAKTOP (2007-03-21 16:24:00) [20]Формируй набор данных через динамическую хранимую процедуру EXECUTE BLOCK, а само тело процедуры (и заодно отчет, ну там метки раскидывай по бэндам) формируй программно в цикле по справочнику, по которому хочешь "развернуть горизонтально".
Только на IBX забей сразу с этими приколами. Воcпользуйся FIBPlus.