Форум OlegON > Программы и оборудование для автоматизации торговли > Системы автоматизации торговли > Супермаг Плюс (Супермаг 2000)

Найти последний документ с артикулом Х : Супермаг Плюс (Супермаг 2000)

23.11.2024 3:02


22.10.2007 17:10
Чего-то не могу родить казалось бы простой запрос.
Мне нужно получить всего одну строчку с идентификатором и типом последнего документа (по дате создания) в котором встречается артикул Х (запрос для 8-го оракла)
о великие гуру
22.10.2007 18:28
Цитата:
SELECT DISTINCT FIRST_VALUE (d.doctype || d.ID) OVER (ORDER BY d.createdat DESC ROWS UNBOUNDED PRECEDING)
FROM smspec s, smdocuments d
WHERE s.article = '00475' AND s.docid = d.ID
Так? Голова уже не варит, извините за ошибки...
22.10.2007 19:52
Цитата:
Mtirt Ты же уже разбирался с этим?
Да, но получил не совсем то, что хотел, как и сейчас...

Цитата:
Olegon Так? Голова уже не варит, извините за ошибки...
Олег, спасибо за отзывчивость, вобщем-то в результате я увидел, то что спросил, но видимо я не так спрашиваю или хочу чего-то невозможного, попробую уточнить.
В данном запросе используется строковое сцепление двух полей, которые в последствии придется разделить. Разделить их можно будет, зная их длину (хотябы первого из них). А что делать, если б понадобилось получить кроме номера и идентификатора еще и, допустим, дату? Расцеплять придется уже три поля, а если поля имеют различную не фиксированную длину?
Поэтому мне нужен результат "грамотный" из одной строки и двух колонок, где первая колонка это тип документа, вторая его идентификатор. И при этом в запросе не использовались строковое сцепление и разцепление. Такое возможно?
23.10.2007 00:28
Нет базы под рукой, ты бы сказал, для чего тебе это. Задачу полностью очертил, а то бери:
Цитата:
SELECT *
FROM smspec s, smdocuments d
WHERE s.article = '00475' AND s.docid = d.ID order by createdat desc
и первую строку из датасета... Можно и одну строку выбрать, просто влом сейчас думать...
23.10.2007 06:57
Приблизительно так?

Код:
 			 				select * from (SELECT 
s.article,
FIRST_VALUE (d.id ) OVER (partition by s.article ORDER BY d.createdat DESC ROWS UNBOUNDED PRECEDING) docid, 
FIRST_VALUE (d.createdat ) OVER (partition by s.article ORDER BY d.createdat DESC ROWS UNBOUNDED PRECEDING) docdate,
row_number() OVER (partition by s.article ORDER BY d.createdat DESC) RN

           FROM smspec s, smdocuments d) where rn=1
Соотвественно конструкцию First)_value () over можно писать для любого значения smdocuments.

А вообще, рекомендую почитать у Кайта про аналитические функции. Там много еще "вкусного" можно найти.
23.10.2007 11:56
Спасибо большое! :)
Скрестив ваши запросы, получил что хотел)))
Код:
SELECT DISTINCT
       FIRST_VALUE (d.doctype) OVER (ORDER BY d.createdat DESC ROWS UNBOUNDED PRECEDING) as doctype,
       FIRST_VALUE (d.ID) OVER (ORDER BY d.createdat DESC ROWS UNBOUNDED PRECEDING) as docid
  FROM supermag.smspec s,
       supermag.smdocuments d
 WHERE s.docid = d.ID
   AND s.doctype = d.doctype
   AND s.article = '014484'
23.10.2007 12:02
Ты главного отличия не понял.
Благодаря функции row_number() и конструкции, приведенной в запросе ты номер последнего прихода можешь получить не для отдельного артикула, а для группы или ассортимента.
А это быстрее, чем искать для каждой записи в отчете.
23.10.2007 12:27
Ссылка на статью Т. Кайта.
23.10.2007 13:50
Цитата:
Mtirt Ссылка на статью Т. Кайта.
За ссылку отдельное спасибо! Узнал новое для себя, значит день уже прошел не зря :)

По поводу row_number() и того что это будет быстрее.
Рассмотрим простой пример, допустим нужно определить цены последних приходов товаров из ассортимента.

Вариант 1, без использования row_number():
Код:
SELECT c.article as "Артикул",
       c.name as "Наименование",
       c.wi_docid as "Номер накладной",
       d.createdat as "Дата прихода",
       dc.itemprice as "Цена прихода"

  FROM supermag.smdocuments d,
       supermag.smspec dc,
(
SELECT c.article,
       c.name,
       (SELECT DISTINCT FIRST_VALUE (wid.ID) OVER (ORDER BY wid.createdat DESC ROWS UNBOUNDED PRECEDING)
          FROM supermag.smspec wis, supermag.smdocuments wid
         WHERE wis.docid = wid.ID AND wis.doctype = wid.doctype AND wid.doctype = 'WI' AND wid.opcode=0
           AND wis.article = c.article
           AND wid.locationto=(4)
       ) as wi_docid
  FROM supermag.smcard c,
       supermag.smcardassort pca,
       supermag.sacardassort ca
       
 WHERE pca.article=c.article
   AND ca.id=pca.idassort
   AND ca.tree LIKE ('2.%')
) c
WHERE d.id=c.wi_docid
  AND d.doctype='WI'
  AND dc.docid=d.id
  AND dc.doctype=d.doctype
  AND dc.article=c.article
Теперь вариант 2, с использованием row_number():
Код:
break on c.article skip 1
SELECT * FROM
(
SELECT c.article as "Артикул",
       c.name as "Наименование",
       d.id,
       d.createdat,
       row_number() over (partition by c.article order by d.createdat desc) rnk,
       dc.itemprice

  FROM supermag.smcard c,
       supermag.smcardassort pca,
       supermag.sacardassort ca,
       supermag.smdocuments d,
       supermag.smspec dc
       
 WHERE pca.article=c.article
   AND ca.id=pca.idassort
   AND d.id=dc.docid
   AND d.doctype=dc.doctype
   AND d.doctype='WI'
   AND d.opcode=0
   AND c.article=dc.article
   AND d.locationto=(4)
   AND ca.tree LIKE ('2.%')
ORDER BY c.article
) WHERE rnk=1
Результаты этих запросов идентичны, только первый (без row_number()) выполняется на моей базе 0,44 секунды, а второй - 34,5 сек, т.е. на порядок медленнее, причем я запускал запрос несколько раз, чтоб обеспечить буферизацию нужных данных.
Или я как-то не так запрос написал?
Часовой пояс GMT +3, время: 03:02.

Форум на базе vBulletin®
Copyright © Jelsoft Enterprises Ltd.
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.