Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Связь двух запросов по ключевому полю


Автор: salik 2.2.2015, 11:30
Здравствуйте уважаемые эксперты.
Помогите разобраться как построить связь один ко многим на простом примере.
Есть запрос, назовем его sel1
Код

select id_table1 from table1 


И запрос sel2
Код

SELECT * from 
(SELECT '1' id_table1, 'какой-то текст1' `name`
UNION
SELECT 2, 'какой-то текст2' ) zapros


Проверил, по отдельности эти запросы работают без ошибок.
Дальше настраиваю вторую таблицу заполняю mastersource, masterfield, indexfielname.
С помощью компонента sqlMonitor видно, следующее

Код

SELECT * from 
(SELECT where id_table = 1 '1' id_table1, 'какой-то текст1' `name`
UNION
SELECT 2, 'какой-то текст2' ) zapros


Если бы был второй запрос простой (без union), то (where id_table = 1) делфи дописал в конец и все было бы замечательно. А так постоянно ставит на это место и сами видите запрос становится ошибочным.

Автор: ТоляМБА 2.2.2015, 13:15
Цитата(salik @  2.2.2015,  13:30 Найти цитируемый пост)
А так постоянно ставит на это место 
Кто ставит? В делфи можно формировать запросы динамически используя переменные и параметры. Напишите как должен выглядеть ваш запрос.

Автор: salik 2.2.2015, 13:51
Попытаюсь объяснить более подробно с вставками кода.
Есть SimpleDataSet1 в котором CommandText
Код

select id_table from table 


Есть SimpleDataSet2 в котором CommandText
Код

SELECT * from 
(SELECT  1 id_table, 'какой-то текст1' `name`
UNION
SELECT 2, 'какой-то текст2' ) zapros


Код

DataSource1.dataset := SimpleDataSet1;
SimpleDataSet2.MasterSource := DataSource1;
SimpleDataSet2.MasterFields := 'id_table';
SimpleDataSet2.IndexFieldNames := 'id_table';


Далее кликаю по Active
Код

SimpleDataSet1.active := true; 


Когда же кликаю
Код

SimpleDataSet2.active := true; 


Выходит ошибка. Смотрю в sqlMonitor какой же запрос он шлет на сервер.
SqlMonitor показывает 
Код

SELECT * from 
(SELECT where id_table = 1 1 id_table, 'какой-то текст1' `name`
UNION
SELECT 2, 'какой-то текст2' ) zapros


А правильный запрос должен быть таким
Код

SELECT * from 
(SELECT 1 id_table, 'какой-то текст1' `name`
UNION
SELECT 2, 'какой-то текст2' ) zapros
where id_table = 1

Автор: ТоляМБА 2.2.2015, 14:13
Попытаюсь понять что вы хотели: есть некая таблица table в которой в поле id_table хранятся целочисленные значения. Вы хотите сделать вывод следующих данных: если id_table =1 то вывести "1 | 'какой-то текст1'" если id_table = 2 то вывести "2 | 'какой-то текст2'" и так далее.
Я правильно понял, нет?

Автор: salik 2.2.2015, 15:06
Цитата(ТоляМБА @ 2.2.2015,  15:13)
Вы хотите сделать вывод следующих данных: если id_table =1 то вывести "1 | 'какой-то текст1'" если id_table = 2 то вывести "2 | 'какой-то текст2'" и так далее.
Я правильно понял, нет?

Вы меня совершенно правильно поняли. Хранимая процедура на срвере генерирует динамический запрос, структуру которого я описал в примере. Заострять внимание на вычисляемых полях и откуда они берутся не стал, поэтму написал "какой-то текст"

Автор: ТоляМБА 2.2.2015, 15:21
Код
SELECT * from 
(SELECT 1 id_table, 'какой-то текст1' as name
UNION
SELECT 2, 'какой-то текст2' ) zapros
inner join [table] t
on zapros.id_table=t.id_table


Не?

Автор: salik 2.2.2015, 16:16
Цитата(ТоляМБА @ 2.2.2015,  16:21)
Код
SELECT * from 
(SELECT 1 id_table, 'какой-то текст1' as name
UNION
SELECT 2, 'какой-то текст2' ) zapros
inner join [table] t
on zapros.id_table=t.id_table


Не?

Спасибо, что пытаетесь помочь. 
Делфи отправляет такой запрос
Код

SELECT zapros.* from 
(SELECT   where id_table = '1' 1 id_table, 'какой-то текст1' as name
UNION
SELECT 2, 'какой-то текст2' ) zapros
inner join table1 av
on zapros.id_table=av.id_table

Как не бьюсь программа вставляет  (where id_table = '1') после второго селекта.

Если посылать такой запрос:
Код

select id_table , name from table2

то получается
Код

  select id_table , name from table2 where id_table = '1' 


Я так понял это глюк компонента, он не понимает составные запросы.

Автор: ТоляМБА 2.2.2015, 16:26
Я не использовал SimpleDataSet, всегда работал с Query и проблем не возникало. Попробуйте через него.

Автор: salik 2.2.2015, 16:35
Цитата(ТоляМБА @ 2.2.2015,  17:26)
Я не использовал SimpleDataSet, всегда работал с Query и проблем не возникало. Попробуйте через него.

Я использую технологию доступа к данным dbExpress, в компоненте TSQLQuery с соответствующей вкладки нет такого свойства как MasterSourse. Это принципиально важно при формировании  master-detail отчетов в FastReport.

Автор: ТоляМБА 2.2.2015, 17:40
Цитата(salik @  2.2.2015,  18:16 Найти цитируемый пост)
Как не бьюсь программа вставляет  (where id_table = '1') после второго селекта.

полагаю если закомменить этот код
Цитата(salik @  2.2.2015,  15:51 Найти цитируемый пост)
DataSource1.dataset := SimpleDataSet1;
SimpleDataSet2.MasterSource := DataSource1;
SimpleDataSet2.MasterFields := 'id_table';
SimpleDataSet2.IndexFieldNames := 'id_table';

то вставляться ничего в запрос не будет.

Автор: salik 3.2.2015, 08:10
Цитата(ТоляМБА @ 2.2.2015,  18:40)
полагаю если закомменить этот код
Цитата(salik @  2.2.2015,  15:51 Найти цитируемый пост)
DataSource1.dataset := SimpleDataSet1;
SimpleDataSet2.MasterSource := DataSource1;
SimpleDataSet2.MasterFields := 'id_table';
SimpleDataSet2.IndexFieldNames := 'id_table';

то вставляться ничего в запрос не будет.

Тогда не будет работать вторая выборка по условию и будет выбрасывать весь набор данных. Принял решение получить набор записей в одном запросе, а красоту наведу с помощью скрипта FastReport.

Автор: ТоляМБА 3.2.2015, 09:30
Цитата(salik @  3.2.2015,  10:10 Найти цитируемый пост)
Тогда не будет работать вторая выборка по условию и будет выбрасывать весь набор данных.
А какое условие то? Его можно включить в код запроса с помощью параметра.

Автор: salik 3.2.2015, 09:46
[QUOTE=ТоляМБА,3.2.2015,  10:30]
Цитата(salik @  3.2.2015,  10:10 Найти цитируемый пост)
А какое условие то? Его можно включить в код запроса с помощью параметра.

Если организовать связь компонентов таким образом:
Код

DataSource1.dataset := SimpleDataSet1;
SimpleDataSet2.MasterSource := DataSource1;
SimpleDataSet2.MasterFields := 'id_table';
SimpleDataSet2.IndexFieldNames := 'id_table';

В момент вызова отчёта FastReport
Код

if frxReport1.PrepareReport then
    frxReport1.ShowPreparedReport;

 будет происходить автоматический перебор записей первого уровня (MasterData), а в запрос второго уровня будет вносится автоматическая корректировка, в нашем случае это where id_table = 1, where id_table = 2 и так далее. Это подставляются значения поля (MasterFields) из главной выборки.
Можно написать запрос с помощью параметра, значения которого контролирует сам программист, тогда логику подстановки нужно описать в скрипте или процедуре.

Автор: ТоляМБА 3.2.2015, 10:17
Цитата(salik @  3.2.2015,  11:46 Найти цитируемый пост)
 будет происходить автоматический перебор записей первого уровня (MasterData), а в запрос второго уровня будет вносится автоматическая корректировка, в нашем случае это where id_table = 1, where id_table = 2 и так далее. Это подставляются значения поля (MasterFields) из главной выборки.
Главная выборка у вас это:
Цитата(salik @  2.2.2015,  15:51 Найти цитируемый пост)
select id_table from table 
То что вы делали средствами делфи (объединяя 2 sql-запроса) я написал с помощью одного sql-запроса. Или есть ещё какие-то условия?
Цитата(salik @  3.2.2015,  11:46 Найти цитируемый пост)
тогда логику подстановки нужно описать в скрипте
Каком скрипте?

Автор: salik 4.2.2015, 08:12
Цитата(ТоляМБА @ 3.2.2015,  11:17)
 Или есть ещё какие-то условия?

Не надо искать черную кошку в черной комнате, если ее там нет. Со связью таблиц главная и подчиненная я разобрался, спасибо. Помощь в написании запроса не требуется. Тема закрыта, вопрос решен. Еще раз спасибо за участие.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)