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

Откуда:
Сообщений: 64
Есть банальнейшая задача составить запрос на выборку данных. Упрощенный вариант задачи:
1 таблица (операции), 4 поля (ID - int, номер объекта - int, код операции с объектом - int, дата получения информации - datetime).
Данные приходят независимо от того, выполнялась операция над объектом или нет. Необходимо написать запрос, в котором не будет дублирующих друг друга операций с вагоном.
Грубо говоря привести данные вида:
1 1 1 2012-10-15 00:00:00
2 2 1 2012-10-15 00:00:00
3 3 1 2012-10-15 00:00:00
4 1 1 2012-10-15 00:00:01
5 2 2 2012-10-15 00:00:01
6 3 1 2012-10-15 00:00:01
К виду:
1 1 1 2012-10-15 00:00:00
2 2 1 2012-10-15 00:00:00
3 3 1 2012-10-15 00:00:00
5 2 2 2012-10-15 00:00:01

Голову сломал. На ум приходит только писать процедуру: сортировать по дате (ASC) и в цикле курсором проходить все значения, сравнивая тип последней операции =\
Может как-нибудь можно это сделать без курсоров?
15 окт 12, 23:00    [13323116]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
ну так что не получается .. тут принято
1.писать усливое с тестовыми данными
2.желаемы результат выборки
3. свой вариант выборки

Да и почему пропала строка
6 3 1 2012-10-15 00:00:01 - код операции 3 уникален для вагона номер 1 ?
15 окт 12, 23:08    [13323142]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
tetxx
Member

Откуда:
Сообщений: 297
Например так:
select *
from T t1
where not exists (select 1 from T t2 where t2.object_id = t1.object_id and t2.op_code = t1.op_code and t2.id < t1.id)


или так:
select top 1 with ties *
from T
order by row_number()over(partition by object_id,op_code order by id)
15 окт 12, 23:39    [13323238]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
tetxx,

Оба два твоих вариант не учитывают чередование операций над объектом.
16 окт 12, 04:39    [13323828]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
hex.style
Member

Откуда:
Сообщений: 64
Maxx
ну так что не получается .. тут принято
1.писать усливое с тестовыми данными
2.желаемы результат выборки
3. свой вариант выборки

А я что сделал не так? Условие есть, тестовые данные привел, желаемый результат тоже. Ну и свой вариант решения мне видится только с курсором, а без него своего варианта нет.

Maxx
Да и почему пропала строка
6 3 1 2012-10-15 00:00:01 - код операции 3 уникален для вагона номер 1 ?

Код операции не уникален. Есть конечное множество операций. Чтобы не усложнять, я взял {1,2}
Уникален только ID записи. Ну и пара вагон/время занесения.
Если код операции не меняется, это логически означает, что запись дублируется.

tetxx, мой промах, тестовый набор не отражал всей сути. Вот так будет правильней:

1 1 1 2012-10-15 00:00:00
2 2 1 2012-10-15 00:00:00
3 3 1 2012-10-15 00:00:00
4 1 1 2012-10-15 00:00:01
5 2 2 2012-10-15 00:00:01
6 3 1 2012-10-15 00:00:01
7 1 1 2012-10-15 00:00:02
8 2 1 2012-10-15 00:00:02
9 3 1 2012-10-15 00:00:02

Выборка:

1 1 1 2012-10-15 00:00:00
2 2 1 2012-10-15 00:00:00
3 3 1 2012-10-15 00:00:00
5 2 2 2012-10-15 00:00:01
7 1 2 2012-10-15 00:00:02
8 2 1 2012-10-15 00:00:02
16 окт 12, 12:03    [13325478]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Александр Бердышев
Member

Откуда: Санкт-Петербург
Сообщений: 349
SELECT * FROM t WITH(NOLOCK)
      WHERE Id IN
      (SELECT MIN(Id) 
            FROM t WITH(NOLOCK)
            GROUP BY номер_объекта, код_операции)
16 окт 12, 13:52    [13326436]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
tetxx
Member

Откуда:
Сообщений: 297
Добрый Э - Эх
Оба два твоих вариант не учитывают чередование операций над объектом.
А при чем тут чередование операций? Об этом в условии ни слова.
Необходимо написать запрос, в котором не будет дублирующих друг друга операций с вагоном.
16 окт 12, 15:11    [13327218]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
tetxx
Добрый Э - Эх
Оба два твоих вариант не учитывают чередование операций над объектом.
А при чем тут чередование операций? Об этом в условии ни слова.
Необходимо написать запрос, в котором не будет дублирующих друг друга операций с вагоном.

Учись читать между строк и угадывать мысли топикстартеров :) Часто люди хотят одно, а пишут - другое.

Не веришь мне - спроси у ТС, что ему нужно показать в такой вот ситуации:
Вагон сначала загрузили, после погрузки - поняли, что загрузили не тем (ну или не в тот вагон), дабы исправить ошибку, вагон разгрузили, затем - повторно загрузили. Итого, в хронологической таблице имеем чередующие операции с вагоном: загрузка - разгрузка - загрузка. Твои запросы покажут всего одну загрузку и одну разгрузку. Вторая загрузка похерится. А в контексте желаний автора - она должна остаться, ибо эти две загрузки - суть разные две операции.

Теперь другая ситуация. Допустим, вагон три дня загружали и в таблице были бы записи вида: загрузка - загрузка - загрузка. Вот в этом случае автору нужно именно одну запись оставить, ибо и так понятно, что операций над вагоном делали всего одну - загрузку. Просто делали это очень долго.


И я тебе скажу больше: если вагон три дня загружали, а после поняли что прокосячили и три дня его разгружали, а затем по новой три дня загружали, то из таблицы вида: загрузка - загрузка - загрузка - разгрузка - разгрузка -разгрузка -загрузка - загрузка - загрузка - должна будет получится таблица вида: загрузка - разгрузка - загрузка.

Это моё видение того, что нужно ТС. Думается, что твои запросы этой задачи не решают...
17 окт 12, 05:50    [13330523]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
hex.style
Есть банальнейшая задача ...
Может как-нибудь можно это сделать без курсоров?
Задача и в самом деле - банальнейшая. Кроме того - заезженный баян. Решается через группировку по инварианту группы (разность двух разнооконных row_number-ов), либо посредством метода "начала групп" (для этого требуется lead/lag функции, что доступно с 2012 сервера, либо ton 1 подзапрос для поиска предыдущих записей)
17 окт 12, 09:34    [13331112]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
bormental
Member

Откуда:
Сообщений: 90
только непонятно все равно после второго разъяснения автора почему,скажем
8 2 1 2012-10-15 00:00:02
попадает в результирующую выборку, а
7 1 1 2012-10-15 00:00:02
нет
17 окт 12, 10:07    [13331320]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
bormental
только непонятно все равно после второго разъяснения автора почему,скажем
8 2 1 2012-10-15 00:00:02
попадает в результирующую выборку, а
7 1 1 2012-10-15 00:00:02
нет
у автора там опечатка. скорее всего, он хотел написать 7 1 2 2012-10-15 00:00:02
17 окт 12, 10:10    [13331347]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
Вариант на группировке по инварианту группы:
--
-- Тестовый набор данных:
with
  t (id, obj_num, oper_code, date) as
    (
      select * 
        from ( values
               (1, 1, 1, '2012-10-15 00:00:00'),
               (2, 2, 1, '2012-10-15 00:00:00'),
               (3, 3, 1, '2012-10-15 00:00:00'),
               (4, 1, 1, '2012-10-15 00:00:01'),
               (5, 2, 2, '2012-10-15 00:00:01'),
               (6, 3, 1, '2012-10-15 00:00:01'),
               (7, 1, 2, '2012-10-15 00:00:02'),
               (8, 2, 1, '2012-10-15 00:00:02'),
               (9, 3, 1, '2012-10-15 00:00:02')
              ) v(i,n,c,d)
      )
--
-- Основной запрос:
select min(id) as start_id, max(id) as end_id,
       obj_num, oper_code,
       min(date) as start_date, max(date) as end_date
  from (
         select t.*, 
                row_number() over(partition by obj_num, oper_code order by date) -
                row_number() over(partition by obj_num order by date) as rn
           from t
       ) v
 group by obj_num, oper_code, rn
 order by 1
17 окт 12, 10:15    [13331391]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
bormental
Member

Откуда:
Сообщений: 90
а
8 2 1 2012-10-15 00:00:02
почему тогда попадает если уже было
2 2 1 2012-10-15 00:00:00
17 окт 12, 10:17    [13331404]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
Вариант по методу "начала групп" (без переделки требует наличие MS SQL Server 2012):
--
-- Набор тестовых данных:
with
  t (id, obj_num, oper_code, date) as
    (
      select * 
        from ( values
               (1, 1, 1, '2012-10-15 00:00:00'),
               (2, 2, 1, '2012-10-15 00:00:00'),
               (3, 3, 1, '2012-10-15 00:00:00'),
               (4, 1, 1, '2012-10-15 00:00:01'),
               (5, 2, 2, '2012-10-15 00:00:01'),
               (6, 3, 1, '2012-10-15 00:00:01'),
               (7, 1, 2, '2012-10-15 00:00:02'),
               (8, 2, 1, '2012-10-15 00:00:02'),
               (9, 3, 1, '2012-10-15 00:00:02')
              ) v(i,n,c,d)
      )
--
-- Основной запрос:
select min(id) as id, max(id) as end_id,
       obj_num, oper_code,
       min(date) as start_date, max(date) as end_date
  from (
         select v0.*, sum(start_of_group) over(partition by obj_num order by date) as grp_id
           from (
                  select t.*, 
                         case lag(oper_code) over(partition by obj_num order by date)
                           when oper_code
                             then 0
                           else 1
                         end as start_of_group
                    from t
                ) as v0
       ) as v1
group by obj_num, oper_code, grp_id
order by 1
17 окт 12, 10:25    [13331448]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
bormental
а
8 2 1 2012-10-15 00:00:02
почему тогда попадает если уже было
2 2 1 2012-10-15 00:00:00
потому что между ними была операция другого типа (5 2 2 2012-10-15 00:00:01), если что...
(то самое чередование, про которое я разъяснял tetxx-у)
17 окт 12, 10:27    [13331467]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
bormental
Member

Откуда:
Сообщений: 90
Добрый Э - Эх
bormental
а
8 2 1 2012-10-15 00:00:02
почему тогда попадает если уже было
2 2 1 2012-10-15 00:00:00
потому что между ними была операция другого типа (5 2 2 2012-10-15 00:00:01), если что...
(то самое чередование, про которое я разъяснял tetxx-у)


Ааа, ясн теперь что хотел автор . спс Добрый Э - Эх )
17 окт 12, 10:31    [13331513]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Добрый Э - Эх
Guest
bormental
Ааа, ясн теперь что хотел автор . спс Добрый Э - Эх )
Ну, напомню - это мое видение того, что хотел автор. Не исключено, что на самом деле нужно нечто иное...
17 окт 12, 10:34    [13331533]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
hex.style
Member

Откуда:
Сообщений: 64
Добрый Э - Эх, спасибо огромное! За участие, понимание и грамотное решение)) Ты мне очень помог!
Запрос решил поставленную задачу, а Lead & Lag в MS SQL 2012 для меня - большое открытие.

*ушел читать матчасть* =)
17 окт 12, 11:52    [13332181]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
_bob
Member

Откуда: Москва
Сообщений: 1654
решение на чистом SQL

идея:
позапрос: строку соединяем со строкой по вагону и минимально мЕньшему времени (получаем предыдущую операцию)
основной запрос выбирает строки, у которых предыдущая операция не равна текущей

сам селект писать лень, т.к. все банально просто
17 окт 12, 15:55    [13334951]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
tetxx
Member

Откуда:
Сообщений: 297
Добрый Э, спасибо за подробное разъяснение. До такого уровня мой хрустальный шар еще качать и качать :)
17 окт 12, 17:25    [13335807]     Ответить | Цитировать Сообщить модератору
 Re: Запрос на выборку без курсора =)  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
tetxx,

я подозреваю что кроме шаров ,он еще хорошо знаком с предметной областью
17 окт 12, 17:26    [13335824]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить