Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Запрос, поиск но нескольким строкам  [new]
Mixon
Member

Откуда:
Сообщений: 336
Приветствую ВСЕХ!
подскажите как решить вот такую задачу, есть таблица:
код_элемента, код_события, порядковый_номер
1,1,1
1,1,2
1,2,3
1,4,4
2,1,1
2,3,2
2,2,3

задача найти такие элементы у которых выполняется условия:
а) *-1-2 (в данном случае номер события 2 должно быть следующим после события 1);
б) 1-*-2 (в данном случае событие 1 ранее события 2, подходят варианты 1-2-3 и 1-3-2);

вообщем с трудом представляю как это реализовать.
ЗЫ фильтр приведен простой в реальности может быть и 1-2-3-4-5-*

С уважением Михаил
28 янв 15, 22:47    [17186198]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Lepsik
Member

Откуда: glubinka
Сообщений: 4256
https://www.sql.ru/forum/rules.aspx

Рекомендуется: При написании сообщений с просьбой о составлении запроса - хорошим тоном считается предоставление скрипта на создание таблицы и заполнение ее тестовыми данными, а также ожидаемого результата выборки, если это не очевидно из вопроса.
28 янв 15, 23:25    [17186376]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
Mixon,

репрезентативный юзабильный набор тестовых данных и желаемый результат на них приведи. А то словесное описание хотелки сильно хромает.
29 янв 15, 05:03    [17187004]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Mixon
Member

Откуда:
Сообщений: 336
declare @t table(id int identity, id_obj int, id_msg int, num int)

--first obj
insert into @t(id_obj, id_msg, num ) values(1,1,1)
insert into @t(id_obj, id_msg, num ) values(1,2,2)
insert into @t(id_obj, id_msg, num ) values(1,2,3)
insert into @t(id_obj, id_msg, num ) values(1,3,4)

--second obj
insert into @t(id_obj, id_msg, num ) values(2,1,1)
insert into @t(id_obj, id_msg, num ) values(2,2,2)
insert into @t(id_obj, id_msg, num ) values(2,3,3)
insert into @t(id_obj, id_msg, num ) values(2,4,4)

select * from @t

а) найти объекты у которых событие "2" следует за событием "1", то есть 1-2
в нашем случае первый объект

и) найти объекты у которых событие "3" следует за событием "1", но не в притык то есть 1-*-3 и 1-3
в нашем случае первый и второй объекты
29 янв 15, 08:26    [17187164]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Mixon
Member

Откуда:
Сообщений: 336
declare @t table(id int identity, id_obj int, id_msg int, num int)

--first obj
insert into @t(id_obj, id_msg, num ) values(1,1,1)
insert into @t(id_obj, id_msg, num ) values(1,2,2)
insert into @t(id_obj, id_msg, num ) values(1,2,3)
insert into @t(id_obj, id_msg, num ) values(1,3,4)

--second obj
insert into @t(id_obj, id_msg, num ) values(2,1,1)
insert into @t(id_obj, id_msg, num ) values(2,2,2)
insert into @t(id_obj, id_msg, num ) values(2,3,3)
insert into @t(id_obj, id_msg, num ) values(2,4,4)

select * from @t

а) найти объекты у которых событие "2" следует за событием "1", то есть 1-2
в нашем случае первый и второй объекты

и) найти объекты у которых событие "3" следует за событием "1", но не в притык то есть 1-*-3 и 1-3
в нашем случае первый и второй объекты
29 янв 15, 08:27    [17187167]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
LexusR
Member

Откуда: Novosibirsk
Сообщений: 1873
 declare @t table(id int identity, id_obj int, id_msg int, num int)

--first obj
insert into @t(id_obj, id_msg, num ) values(1,1,1)
insert into @t(id_obj, id_msg, num ) values(1,2,2)
insert into @t(id_obj, id_msg, num ) values(1,2,3)
insert into @t(id_obj, id_msg, num ) values(1,3,4)

--second obj
insert into @t(id_obj, id_msg, num ) values(2,1,1)
insert into @t(id_obj, id_msg, num ) values(2,2,2)
insert into @t(id_obj, id_msg, num ) values(2,3,3)
insert into @t(id_obj, id_msg, num ) values(2,4,4)

select * from @t
/*
а) найти объекты у которых событие "2" следует за событием "1", то есть 1-2
в нашем случае первый и второй объекты
*/

select t1.* from @t t1
where exists(
select * from @t t2 where t1.id_obj = t2.id_obj
and t1.id_msg = 1 and t2.id_msg = 2 and t2.num =t1.num+1)

/*
и) найти объекты у которых событие "3" следует за событием "1", но не в притык то есть 1-*-3 и 1-3
в нашем случае первый и второй объекты  
*/
select t1.* from @t t1
where exists(
select * from @t t2 where t1.id_obj = t2.id_obj
and t1.id_msg = 1 and t2.id_msg = 3 and t2.num > t1.num)
29 янв 15, 08:52    [17187229]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
LexusR,

есть подозрение, что не взлетит. ибо со слов автора:
Mixon
ЗЫ фильтр приведен простой в реальности может быть и 1-2-3-4-5-*

С уважением Михаил
29 янв 15, 09:13    [17187318]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
Mixon,

в целом, напрашивается рекурсивный СТЕ для построения дерева переходов по исходным данным. далее - фильтрации по "пути переходов"
29 янв 15, 09:14    [17187329]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20581
Фильтр любой сложности в данном случае можно разбить на связную группу простых фильтров (связывающих только два элемента фильтра).

Обработка одного такого фильтра уже показана. WHERE EXISTS позволяет собрать любое количество простых фильтров воедино. Для упрощения желательно, чтобы существовал базовый элемент - т.е. входящий в каждый из простых фильтров. Парсинг сложного фильтра в SQL-текст (на клиенте) мне не кажется сложной.
29 янв 15, 09:57    [17187568]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20581
Стоп. Я неправ, сложности есть. Нельзя толкаться от базового фильтра - если в середине встретится шаблон-звёздочка, будут проблемы.

В любом случае тогда можно обработать фильтр, используя несколько копий таблицы, причём каждая пара таблиц будет обрабатывать смежную пару элементов шаблона. Скажем, для фильтра *-1-2-*-3-* получится
WHERE t1.num<t2.num AND t2.msg = 1
  AND t2.num = t3.num-1 AND t3.num = 2
  AND t3.num < t4.num AND t4.num = 3
  AND t4.num < t5.num
29 янв 15, 10:11    [17187639]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20581
Впрочем, работать этот хлам будет архимедленно. И индексы не помогут - ну разве что ввести индекс по счётному полю (num-1)...

Наверное, быстрее будет пробежаться по группе записей курсором и сравнить её с шаблоном.
29 янв 15, 10:13    [17187646]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
Mixon,
-- фильтр переходов в формате '%->x->y':
-- если номер переходя не важен, то вместо него пишем '%'
declare @filtr varchar(max); 
    set @filtr = '1->%->4';

declare @t table(id int identity, id_obj int, id_msg int, num int);
    
--first obj
insert into @t(id_obj, id_msg, num ) values(1,1,1);
insert into @t(id_obj, id_msg, num ) values(1,2,2);
insert into @t(id_obj, id_msg, num ) values(1,2,3);
insert into @t(id_obj, id_msg, num ) values(1,3,4);

--second obj
insert into @t(id_obj, id_msg, num ) values(2,1,1);
insert into @t(id_obj, id_msg, num ) values(2,2,2);
insert into @t(id_obj, id_msg, num ) values(2,3,3);
insert into @t(id_obj, id_msg, num ) values(2,4,4);

--
-- Основной запрос:
with
-- Строим дерево переходов:
  v(id, id_obj, id_msg, num, x_path) as
    (
      select id, id_obj, id_msg, num, '->' + cast(id_msg as varchar(max))
        from @t t
       where num = 1
       union all
      select t.id, t.id_obj, t.id_msg, t.num, v.x_path+ '->' + cast(t.id_msg as varchar(max))
        from @t t 
        join v 
          on v.id_obj = t.id_obj
         and v.num = t.num - 1
    ),
-- Забыл, как выделить ветвь дерева, поэтому тупо так:
  c(id, id_obj, id_msg, num, x_path) as
    (
      select id, id_obj, id_msg, num, max(x_path) over(partition by id_obj)
        from v
    )
-- 
-- Выбираем из полученного дерева эелементы, 
-- удовлетворяющие фильтру поиска:
select id, id_obj, id_msg, num
  from c
 where x_path like '%' +  @filtr + '%'
order by id
29 янв 15, 10:22    [17187689]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
Добрый Э - Эх,

чего-то с форматом фильтра немного недомудрил. нужно чутка допилить...
29 янв 15, 10:27    [17187710]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
Добрый Э - Эх
Добрый Э - Эх,

чего-то с форматом фильтра немного недомудрил. нужно чутка допилить...
или не нужно? короче, пусть ТС сам разбирается
29 янв 15, 10:29    [17187724]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Glory
Member

Откуда:
Сообщений: 104760
declare @t table(id int identity, id_obj int, id_msg int, num int)

--first obj
insert into @t(id_obj, id_msg, num ) values(1,1,1)
insert into @t(id_obj, id_msg, num ) values(1,2,2)
insert into @t(id_obj, id_msg, num ) values(1,2,3)
insert into @t(id_obj, id_msg, num ) values(1,3,4)

--second obj
insert into @t(id_obj, id_msg, num ) values(2,1,1)
insert into @t(id_obj, id_msg, num ) values(2,2,2)
insert into @t(id_obj, id_msg, num ) values(2,3,3)
insert into @t(id_obj, id_msg, num ) values(2,4,4)

--fird obj
insert into @t(id_obj, id_msg, num ) values(3,2,1)
insert into @t(id_obj, id_msg, num ) values(3,1,2)
insert into @t(id_obj, id_msg, num ) values(3,3,3)
insert into @t(id_obj, id_msg, num ) values(3,4,4)

select id_obj from @t a
where id_msg in(1,2)
group by id_obj having count(distinct id_msg) = 2 and min(case when id_msg=1 then num end) < max(case when id_msg=2 then num end)
29 янв 15, 10:33    [17187742]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Mixon
Member

Откуда:
Сообщений: 336
Спасибо ВСЕМ, буду разбирать ваши примеры.
29 янв 15, 10:50    [17187844]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
Mixon,

если будешь разбирать мой пример, то поменяй формат объявления фильтра с 'x->%->y': на: 'x->*->y'
и в итоговом запрос замени условие фильтрации с: x_path like '%' + @filtr + '%' на x_path like '%' + replace(replace(@filtr,'*','%'),'->%','%') + '%'
29 янв 15, 10:55    [17187860]     Ответить | Цитировать Сообщить модератору
 Re: Запрос, поиск но нескольким строкам  [new]
Добрый Э - Эх
Guest
Добрый Э - Эх,

в общем, вот так примерно должно всё выглядеть:
declare @filtr varchar(max); 
declare @t table(id int identity, id_obj int, id_msg int, num int);
    set @filtr = '1->*->2';
    
--first obj
insert into @t(id_obj, id_msg, num ) values(1,1,1);
insert into @t(id_obj, id_msg, num ) values(1,0,2);
insert into @t(id_obj, id_msg, num ) values(1,2,3);
insert into @t(id_obj, id_msg, num ) values(1,3,4);
--second obj
insert into @t(id_obj, id_msg, num ) values(2,1,1);
insert into @t(id_obj, id_msg, num ) values(2,2,2);
insert into @t(id_obj, id_msg, num ) values(2,3,3);
insert into @t(id_obj, id_msg, num ) values(2,4,4);

with
  v(id, id_obj, id_msg, num, x_path) as
    (
      select id, id_obj, id_msg, num, '->' + cast(id_msg as varchar(max))
        from @t t
       where num = 1
       union all
      select t.id, t.id_obj, t.id_msg, t.num, v.x_path+ '->' + cast(t.id_msg as varchar(max))
        from @t t 
        join v 
          on v.id_obj = t.id_obj
         and v.num = t.num - 1
    ),
  c(id, id_obj, id_msg, num, x_path) as
    (
      select id, id_obj, id_msg, num, max(x_path) over(partition by id_obj)
        from v
    )
-- 
--
select id, id_obj, id_msg, num
  from c
 where x_path like '%' +  replace(replace(@filtr,'*','%'),'->%','%') + '%'
order by id
29 янв 15, 10:57    [17187871]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить