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

Ваш аккаунт

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

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

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

Выбрать только записи, пренадлежащие к группе и ее подгруппам

1
06 января 2012 года
kot_
7.3K / / 20.01.2000
Версия БД - ASE SQL Server/12.5/P/Generic/OS/1/OPT/Sat Jun 30 00:01:37 PDT 2001
Имеется таблица:
 
Код:
CREATE TABLE dbo.tmc
(
ITEM_ID CHAR(14) NOT NULL,
NAME CHAR(25) NOT NULL
ISGROUP NUMERIC(1,0) NULL,
LEVEL_ NUMERIC(1,0) NULL,
PARENT CHAR(14) NULL,
CONSTRAINT kod PRIMARY KEY (KOD)
)

Тестовые данные:
Код:
INSERT INTO dbo.tmc(ITEM_ID,NAME,ISGROUP,LEVEL_,PARENT)
VALUES ('1','Группа,из нее надо выбрать',1,1,'')
INSERT INTO dbo.tmc(ITEM_ID,NAME,ISGROUP,LEVEL_,PARENT)
VALUES ('1499','Группа,дочерняя из нее тоже',1,2,'1')
INSERT INTO dbo.tmc(ITEM_ID,NAME,ISGROUP,LEVEL_,PARENT)
VALUES ('1479','Запись которую надо',0,3,'1')
INSERT INTO dbo.tmc(ITEM_ID,NAME,ISGROUP,LEVEL_,PARENT)
VALUES ('8','Группа дочерняя2 из нее тоже',1,3,'1499')
INSERT INTO dbo.tmc(ITEM_ID,NAME,ISGROUP,LEVEL_,PARENT)
VALUES ('10','Запись которую надо2',0,5,'8')
INSERT INTO dbo.tmc(ITEM_ID,NAME,ISGROUP,LEVEL_,PARENT)
VALUES ('20','Группа не надо выбирать',1,1,'')
INSERT INTO dbo.tmc(ITEM_ID,NAME,ISGROUP,LEVEL_,PARENT)
VALUES ('25','Запись не должна быть выбрана',0,2,'20')

Задача стоит в следующем - выбрать только те записи, которые пренадлежат к указаной группе и ее подгруппам. Т.е. например у меня есть ХП которая возвращает тру либо фалс - если запись соответственно принадлежит либо не принадлежит требуемой группе. По идее нужен запрос вида
 
Код:
select t.item_id, t.name from tmc t where ... AND EXEC is_group(t.parent) = 1

но как это реализовать в указанной БД?
277
06 января 2012 года
arrjj
1.7K / / 26.01.2011
Поидее так:
 
Код:
elect t.item_id, t.name FROM tmc t WHERE ... AND is_group(t.parent) = 1

должно отрабатывать
277
06 января 2012 года
arrjj
1.7K / / 26.01.2011
Хотя в sybase'e возможно придется создать proxy - табличку для хранимой процедуры.
1
06 января 2012 года
kot_
7.3K / / 20.01.2000
по идее да, вроде как бы должно. Но тогда бы и вопроса не было. :) Вот такой запрос
 
Код:
SELECT
    KOD,
    KUZOV,
    PARENT FROM dbo.f_spr_tmc t
WHERE KUZOV !='' AND kuzov like '444' AND dbo.sp_in_group(PARENT,'1') = 1

дает вот такую ошибку
Цитата:
Error (2809) The request for function 'dbo.sp_in_group' failed because 'dbo.sp_in_group' is a procedure object.


т.е. мне получается надо создавать пользовательскую функцию? как это делается в сайбесе? Но вообще то если это возможно - как в запросе получить возвращаемое значение из процедуры?

277
06 января 2012 года
arrjj
1.7K / / 26.01.2011
Для 15-го
http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc36272.1502/html/commands/CHDEDGJI.htm
http://www.sypron.nl/udf.html#sqludf
В 12-м функции только как обертки для java.
http://infocenter.sybase.com/help/topic/com.sybase.dc36271_36272_36273_36274_1250/html/refman/BABBABJC.htm
Поетому скорее всего придется делать с прокси табличкой.

[COLOR="silver"]sap такой sap[/COLOR]
1
06 января 2012 года
kot_
7.3K / / 20.01.2000
Текущее решение - открыть курсор (либо временную таблицу) в процедуре - пройтись по ней и удалить все записи для которых процедура возращает 0 - и оставшееся вернуть клиенту. но мне кажется что это немного не оптимально.
277
06 января 2012 года
arrjj
1.7K / / 26.01.2011
Цитата: kot_
... но мне кажется что это немного не оптимально.



Как вариант если одна большая табличка не помешает, то можно так

1
06 января 2012 года
kot_
7.3K / / 20.01.2000
Да, это неплохое решение, которое позволяет быстро и эффективно делать выборки. Но есть одна проблема - база полна данных, четких критериев нет и наполняемость этой таблицы вне моего контроля - т.е. как любят писать ТП во вконтактике - "все сложно" :)
Поэтому мое решение - использовать две процедуры и временную таблицу с курсором.
У меня это выглядит так - первая процедура всего навсего определяет входит ли запись в требуемую группу:
Код:
CREATE PROCEDURE dbo.sp_in_group
                  @tree_id CHAR(14), /*Родительский идентификатор текущей записи*/
                  @group_id CHAR(14) /*Идентификатор группы на принадлежность  к которой проверяем*/

AS
DECLARE @current_id CHAR(14)
BEGIN
  WHILE (@tree_id IS NOT NULL AND @tree_id <>'')
    BEGIN
/*Выбрали запись - проверили ее - если родитель пустой - завершаем  - это корень дерева*/
    select @current_id = t.kod, @tree_id = rtrim(t.parent)
    from f_spr_tmc t
    WHERE t.kod = @tree_id
  end  
  IF @group_id = @current_id /*если идентификаторы совпадают - то хорошо*/
    RETURN 1
  ELSE
    RETURN 0
   
   
END

В процедуру естественно надо передавать идентификатор корневой папки - но не стоставляет труда модифицировать процедуру так, что бы проверяла на любом уровне вложенности. Думаю это понятно.
И процедура которая обрабатывает данные:
Код:
CREATE PROCEDURE dbo.sp_select_auto
                  @kusov VARCHAR(25)
AS
BEGIN

DECLARE @current_id CHAR(14)
DECLARE @current_parent CHAR(14)
DECLARE @current_body CHAR(25)
DECLARE @result INT

/*создали таблицу, назначили ей первичный ключ - так как курсор у нас модифицирующий*/
CREATE TABLE #tmp_list_cars
(item_id CHAR(14),body_numb CHAR(25),parent CHAR(14),   CONSTRAINT kod PRIMARY KEY (item_id))
/*заполнили ее*/
INSERT #tmp_list_cars
SELECT kod,kuzov,parent FROM f_spr_tmc WHERE KUZOV !='' AND KUZOV LIKE ('%'+rtrim(@kusov)+'%')
/*курсор создали*/
DECLARE list_cars CURSOR FOR SELECT item_id,body_numb,parent FROM #tmp_list_cars
FOR UPDATE
/*Открыли*/
OPEN list_cars

FETCH list_cars INTO @current_id,@current_body,@current_parent

WHILE @@sqlstatus = 0
 BEGIN
  EXEC @result = sp_in_group @current_parent,'1'
   
  IF @result = 0
   BEGIN
        DELETE FROM #tmp_list_cars WHERE current of list_cars
   END
     
  FETCH list_cars INTO @current_id,@current_body,@current_parent
 END

 CLOSE list_cars
 deallocate CURSOR list_cars /*убираем за собой*/

SELECT item_id AS auto_id, body_numb AS kuzov FROM #tmp_list_cars

DROP TABLE #tmp_list_cars
   
END

вот такое решение в данном случае. А вообще конечно в норме стоит использовать промежуточную таблицу - это весьма упрощает жизнь и ускоряет выборки.
Ну и да - у кого есть решение по-лучше (кроме как написать явовскую обертку, либо сменить версию сервера) то опишите.
Христос народився! Славимо його! С праздником.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог