IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.
Модератор: kdv
-
ostin
- Сообщения: 10
- Зарегистрирован: 10 сен 2007, 19:32
Сообщение
ostin » 23 дек 2007, 21:02
Помогите разобраться. Мне нужно выбрать из таблице записи с возможность отфильтровать ее по 4 полям или по 3, вообщем зависит от пользователя по каким параметрам ему нужно получит отчет, все поля не null.
Так я представляю себе эту процедуру так,
Код: Выделить всё
CREATE PROCEDURE new (
a integer,
b integer,
c integer,
d integer)
RETURNS (
id INTEGER)
AS
BEGIN
for select id
from table1
where field1 = :a and field2 = :b and field3 = :c and field4 = :d
into :id
do
suspend;
END
где может быть так
where field1 = 1 and field2 = 2 and field3 = 3 and field4 = 4
или так
where field1 is not null and field2 = 1 and field3 = 2 and field4 = 3
каким способом можно это реализовать.
-
kdv
- Forum Admin
- Сообщения: 6595
- Зарегистрирован: 25 окт 2004, 18:07
Сообщение
kdv » 23 дек 2007, 23:04
а зачем для этого процедуру городить?
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 24 дек 2007, 12:03
Самое правильное решение тут - это формировать запрос динамически на клиенте по заданным условиям фильтра. И едиственное решение в случае большого числа фильтруемых записей.
Есть ещё путь, но это только когда некуда деваться, а именно
where (Field1 is null or Field1 = :a) and (Field2 is null or Field2 = :b) ...
Это позволит отключить фильтр по полю, если передать в параметр null.
Однако, если записей не 100, то производительность упадёт катастрофически (индексы не используются для отбора по таким условиям), выборка 1 записи, попадающей под условия, будет выполняться столько же, сколько целиком выборка без условий.
-
Кузнецов Евгений
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
Сообщение
Кузнецов Евгений » 24 дек 2007, 12:59
WildSery писал(а):
Самое правильное решение тут - это формировать запрос динамически на клиенте по заданным условиям фильтра. И едиственное решение в случае большого числа фильтруемых записей.
В FB 2 можно выкрутиться через IS NOT DISTINCT FROM
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 24 дек 2007, 13:31
Кузнецов Евгений писал(а):В FB 2 можно выкрутиться через IS NOT DISTINCT FROM
Что-то не могу сообразить, какое должно быть условие.
Ведь если параметр будет NULL, то и найдены будут только значения NULL?
-
Кузнецов Евгений
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
Сообщение
Кузнецов Евгений » 24 дек 2007, 14:58
WildSery писал(а):
Ведь если параметр будет NULL, то и найдены будут только значения NULL?
Стормозил, каюсь - IS DISTINCT ничем не поможет.
Единственное замечание - для
WildSery писал(а):
where (Field1 is null or Field1 = :a) and (Field2 is null or Field2 = :b) ...
индексы всё же могут использоваться.
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 24 дек 2007, 15:40
Кузнецов Евгений писал(а):индексы всё же могут использоваться.
Это каким образом?
-
Кузнецов Евгений
- Сообщения: 144
- Зарегистрирован: 16 фев 2006, 22:36
Сообщение
Кузнецов Евгений » 24 дек 2007, 16:12
WildSery писал(а):Это каким образом?
Ну для
Код: Выделить всё
select * from test_table2
where (Field1 is null or Field1 = :a) and
(Field2 is null or Field2 = :a)
план следующий
Код: Выделить всё
PLAN (TEST_TABLE2 INDEX (TEST_W2, TEST_W2, TEST_W1, TEST_W1))
Test_w1 - индекс по Field1
Test_w2 - индекс по Field2
-
DMA
- Сообщения: 6
- Зарегистрирован: 24 дек 2007, 17:03
Сообщение
DMA » 24 дек 2007, 17:09
А может так: select * from test_table2
where (Field1 = :a or :a is null) and
(Field2 = :b or :b is null) and
(Field3 = :c or :c is null) and
(Field4 = :d or :d is null)
-
WildSery
- Заслуженный разработчик
- Сообщения: 1738
- Зарегистрирован: 05 июн 2006, 16:19
Сообщение
WildSery » 24 дек 2007, 17:16
Тьфу ты, точно.
Прошу прощения, это я пример неправильный изначально написал, и больше на него не смотрел, и получается что гоню ерунду.
На самом деле, я хотел написать
Код: Выделить всё
where (cast(:a as int) is null or Field1 = :a) and (cast(:b as int) or Field2 = :b)
Вариант без каста прокатит в случае процедуры, где тип параметра явно определён.
-
ostin
- Сообщения: 10
- Зарегистрирован: 10 сен 2007, 19:32
Сообщение
ostin » 26 дек 2007, 19:51
Спасибо всем кто ответил мне. прочитав все я буду искать наилучшие вариант решения моей проблемы. Спасибо еще раз