Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Выполнение сложных запросов на стороне сервера

6
12 ноября 2009 года
George
4.1K / / 05.01.2007
Вот такой вопрос у меня сегодня появился.
Нужно было сделать отчет, который кроме выборки из таблицы включает итоговые записи (итоговая запись - это как бы сумма всех записей). Сделал с помощью вьюшки что то вроде:
[highlight=sql]
CREATE VIEW my_view (
date_field,
str_field,
int_field
)
AS
SELECT CAST(NULL AS DATE), 'ИТОГО:', SUM(int_field) FROM my_table
UNION
SELECT date_field, 'ИТОГО:', SUM(int_field) FROM my_table
GROUP BY date
UNION
SELECT * FROM my_table
;
[/highlight]
В результате в наборе данных будет вся таблица плюс итоги за каждый день плюс общий итог. Все бы хорошо, да вьюшка не позволяет передавать ей параметры. Дело в том, что мне надо делать выборку например в зависимости от периода. Если я делаю
[highlight=sql]
SELECT * FROM my_view WHERE date_field = :DATE
[/highlight]
то получается, что общий итог будет неверным, ведь он считается не по выбранным записям, а по всей таблице.
Писать большой запрос на стороне клиента (там около 50 строк, потому что здесь итоги я показал в очень упрощенном виде) мне не хочется. Если на стороне сервера, то вьюшки не подходят по вышеприведенным причинам, посмотрел на хп - они возвращают только одну запись, а не набор данных.
В общем попытаюсь сформулировать задачу:
Нужно создать на сервере что-то вроде вьюшки, но которая принимает параметры и динамически делает запрос с их применением, затем возвращает итоговый набор данных. Как можно решить такую задачу?

И да, если что БД - Firebird.
12K
12 ноября 2009 года
Ghox
297 / / 26.07.2009
А проблема в чем?
В том что вьюха содержит три разнородных группы записей, получаемых:
1-я группа записей (содержит одну запись) - получена суммированием по всей таблице;
2-я группа записей - получена группировкой по датам
3-я группа - просто записи взятые из таблицы
Цитата: Washington
Все бы хорошо, да вьюшка не позволяет передавать ей параметры. Дело в том, что мне надо делать выборку например в зависимости от периода. Если я делаю
[highlight=sql]
SELECT * FROM my_view WHERE date_field = :DATE
[/highlight]
то получается, что общий итог будет неверным, ведь он считается не по выбранным записям, а по всей таблице.


И проблема в том, что в одном случае - нужно при выборке брать записи только из одной группы, в другом - из другой и т.д.?
Если я правильно понял суть проблемы, то в Oracle в данном случае можно было бы в каждом из образующих въюху подзапросов добавить фиктивный столбец - индикатор того, каким из подзапросов получена данная запись вьюхи, и при запросе из въюхи использовать условие по этому столбцу.
Как-то так:
[highlight="SQL"]create view my_view
AS
SELECT NULL AS date_field, 'ИТОГО:' AS str_field,
SUM(int_field) AS int_field, 1 AS period FROM my_table
UNION
SELECT date_field, 'ИТОГО:' AS str_field,
SUM(int_field) AS int_field, 2 AS period FROM my_table
GROUP BY date_field
UNION
SELECT /*список полей*/, 3 AS period FROM my_table[/highlight]
И потом в запросе из вьюхи еще накладывать условие на столбец period.
Может и в Firebird можно как-то аналогично...

6
12 ноября 2009 года
George
4.1K / / 05.01.2007
ты меня не понял. вообще.
представь себе, что содержится во вьюхе. всякие строки + сумма строк (буду так называть ее) всей таблицы. теперь мне надо сделать выборку за определенный период. делаю из вьюхи. получаю всякие строки + сумма строк всей таблицы. а надо всякие строки + сумма строк за период. но во вьюху никак ведь не передашь даты как параметры.
1
12 ноября 2009 года
kot_
7.3K / / 20.01.2000
Цитата: Washington

Если на стороне сервера, то вьюшки не подходят по вышеприведенным причинам, посмотрел на хп - они возвращают только одну запись, а не набор данных.


процедура может возвращать и набор данных - в чем проблема то?

6
12 ноября 2009 года
George
4.1K / / 05.01.2007
в том, что она почему то возвращать не хочет. сделал так
[highlight=sql]
CREATE PROCEDURE my_proc
RETURNS (
date DATE,
int INTEGER,
str VARCHAR(200)
)
AS
BEGIN
SELECT CAST(NULL AS DATE), 'ИТОГО:', SUM(int_field) FROM my_table
UNION
SELECT date_field, 'ИТОГО:', SUM(int_field) FROM my_table
GROUP BY date
UNION
SELECT * FROM my_table
INTO :date, :int, :str;
SUSPEND;
END;
[/highlight]
При попытке селекта из процедуры:
[highlight=sql]SELECT * FROM my_proc
[/highlight]
получаю ошибку:
[quote=firebird]
Multiple rows in singleton select.
Multiple rows in singleton select.
At procedure 'my_proc' line: 8, col: 3.[/quote]
1
12 ноября 2009 года
kot_
7.3K / / 20.01.2000
он тебе говорит что твой запрос возвращает много записей а ты пытаешься выбрать одну. Используй кострукцию
Код:
FOR
SELECT CAST(NULL AS DATE), 'ИТОГО:', SUM(int_field) FROM my_table

  UNION

  SELECT date_field, 'ИТОГО:', SUM(int_field) FROM my_table

  GROUP BY date

  UNION

  SELECT * FROM my_table

  INTO :date, :int, :str DO;

и не используй * в выборке - указывай конкретные поля. Кстати советую разделять пользовательское представление и данные.
6
12 ноября 2009 года
George
4.1K / / 05.01.2007
Собственно сделал:
[highlight=sql]
CREATE PROCEDURE my_proc
RETURNS (
date DATE,
int INTEGER,
str VARCHAR(200)
)
AS
BEGIN
FOR
SELECT CAST(NULL AS DATE), 'ИТОГО:', SUM(int_field) FROM my_table
UNION
SELECT date_field, 'ИТОГО:', SUM(int_field) FROM my_table
GROUP BY date
UNION
SELECT * FROM my_table
INTO :date, :int, :str
DO
SUSPEND;
END; [/highlight]

Спасибо за совет =)

Цитата: kot_
и не используй * в выборке - указывай конкретные поля.


ага. это я просто в примере так сделал, а вообще да, указываю.

Ну и в продолжение темы:

Цитата: kot_
Кстати советую разделять пользовательское представление и данные.


так я вроде стараюсь. что именно ты имеешь ввиду в данном случае?

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог