среда, 26 марта 2014 г.
вторник, 25 марта 2014 г.
Пользовательские фильтры в запросе
Рассмотрим типичную задачу построение выборки.
Предположим имеется таблица "A" с некоторыми полями, пользователю необходимо дать
возможность построения условия WHERE в запросе
SELECT по определённым, заранее известным полям. Пусть эти поля
называются N1, N2, Nk.
Дальнейшее изложение идёт для T-SQL MS SQL Server.
Создадим таблицу для записи пользовательского условия
WHERE :
CREATE TABLE [RATIFICATION](
[FNUM] [int] NOT NULL,
[ANUM] [int] NOT NULL,
[EXPR] [varchar](4) NULL,
[VAL] [varchar](255) NULL
)
CREATE INDEX inx_RATIFICATION_F ON RATIFICATION (FNUM)
GO
CREATE INDEX inx_RATIFICATION_A ON RATIFICATION (ANUM)
GO
FNUM | ANUM | EXPR | VAL |
1 | 1 | N1 | AA |
1 | 1 | -N2 | BB |
1 | 2 | N3 | CC |
Построим функцию fn_CheckRatification (@FNUM INT, @N1 VARCHAR(255), @N2 VARCHAR(255), @Nk VARCHAR(255)), которая по номеру фильтра @FNUM и для значений @N1, @N2 и @Nk возвращает число большее нуля в случае если выражение принимает значение "истинно" и ноль в случае "ложь". Тогда условие WHERE для запроса SELECT может быть записана с использованием параметра @FNUM - номер фильтра:
SELECT ... FROM A WHERE dbo.fn_CheckRatification (@FNUM, A.N1, A.N2, A.Nk) > 0
Далее, приводится текст функции fn_CheckRatification. Основная идея такова, с помощью операторов CASE по каждой строке возвращается поле 1 (истина) или 0 (ложь) для проверки условия равенства (неравенства) значению VAL. Далее берется группировка по полю ANUM, а в качестве агрегатной функции берётся среднее AVG операторов CASE. Так получаем проверку условий "И". Сумма по этому агрегатному полю даст проверку условий "ИЛИ"
CREATE FUNCTION [dbo].[fn_CheckRatification] (@FNUM INTEGER, @N1 VARCHAR(255), @N2 VARCHAR(255), @N3 VARCHAR(255) ) RETURNS INTEGER AS BEGIN DECLARE @RES INTEGER SET @RES = ( SELECT SUM(A.EX) FROM (SELECT ANUM, AVG( CASE EXPR WHEN 'N1' THEN CASE WHEN @N1 = VAL THEN 1 ELSE 0 END WHEN '-N1' THEN CASE WHEN @N1 <> VAL THEN 1 ELSE 0 END WHEN 'N2' THEN CASE WHEN @N2 = VAL THEN 1 ELSE 0 END WHEN '-N2' THEN CASE WHEN @N2 <> VAL THEN 1 ELSE 0 END WHEN 'Nk' THEN CASE WHEN @Nk = VAL THEN 1 ELSE 0 END WHEN '-Nk' THEN CASE WHEN @Nk <> VAL THEN 1 ELSE 0 END WHEN 'F' THEN CASE WHEN (dbo.fn_CheckRatification(VAL, @N1, @N2, @Nk) > 0) THEN 1 ELSE 0 END WHEN '-F' THEN CASE WHEN (dbo.fn_CheckRatification(VAL, @N1, @N2, @Nk) >0) THEN 0 ELSE 1 END END ) EX FROM RATIFICATION (NOLOCK) WHERE FNUM = @FNUM GROUP BY ANUM) A ) SET @RES = ISNULL(@RES, 0) RETURN @RES END GO
Подписаться на:
Сообщения (Atom)