[ОТВЕТИТЬ]
26.12.2007 07:46
isi
 
собственно сабж, я использую ROWNUM и потом получаю первую запись, но что то для больших объемов тяжеловато, поделитесь решениями может у кого что оригинальное есть
26.12.2007 08:51
Mtirt
 
Вот здесь https://olegon.ru/showthread.php?t=2628&page=4&highlight=%F6%E5%ED%E0+%ED%E0+%E4%E0%F2%F3 YuraZ в составе запроса выкладывал достаточно интересный поиск цены.

Попробуй.
26.12.2007 09:13
isi
 
Меня интересует имеено цена прихода, а не розницы
26.12.2007 11:41
isi
 
Пока сделал функцию, вроде достаточно быстро работает, давайте свои варианты:

FUNCTION LAST_PRIHOD (
v_art IN VARCHAR2,
v_storeloc IN PLS_INTEGER,
v_date IN DATE
)
RETURN NUMBER
IS
CURSOR mycursor
IS
SELECT /*+ FIRST_ROWS */ smdocuments.createdat, itemprice
FROM smdocuments, smspec
WHERE smdocuments.doctype = smspec.doctype
AND smdocuments.ID = smspec.docid
AND smdocuments.docstate IN (2, 3)
AND smdocuments.doctype IN ('WI', 'PO')
AND smdocuments.userop IS NULL
AND smdocuments.opcode = 0
AND smdocuments.createdat <=
TO_DATE (TO_CHAR (v_date, 'DDMMYYYY'), 'DDMMYYYY')
AND smdocuments.locationto = v_storeloc
AND smspec.article = v_art
ORDER BY smdocuments.createdat DESC;

mycursor_rec mycursor%ROWTYPE;
v_itemprice NUMBER;
BEGIN
OPEN mycursor;

FETCH mycursor
INTO mycursor_rec;

IF NOT mycursor%NOTFOUND
THEN
v_itemprice := mycursor_rec.itemprice;
ELSE
v_itemprice := 0;
END IF;

CLOSE mycursor;

RETURN v_itemprice;
END;
27.12.2007 14:27
Mihon
 
Я бы так сделал : max по дате, но дата меньше systime.
28.12.2007 03:28
isi
 
Цитата:
Mihon Я бы так сделал : max по дате, но дата меньше systime.
Я что то не так понял, как это "max по дате" в условии возможно?

Да кстати попробую порыть в аналитических функциях, там тоже много чего интересного.
28.12.2007 08:40
Mihon
 
Цитата:
isi Я что то не так понял, как это "max по дате" в условии возможно?
Либо 1-м запросом выбирать макс. дату в переменную, потом юзать,
либо вложенным запросом
28.12.2007 09:57
Mtirt
 
У меня вот такой вариант завалялся, похоже это вообще из SpotLight-а выдернули. Я такого точно не писала.
Код:
SELECT /*+ ORDERED USE_NL(S T) FULL(G) INDEX(S) INDEX(T)  */
 G.LOCID AS locid ,
 G.ARTICLE AS article ,
 SUM(S.QUANTITY) AS qty ,
 ROUND(SUM(S.TOTALPRICE) /
       DECODE(SUM(S.QUANTITY), 0, NULL, SUM(S.QUANTITY)),
       1) AS price1 ,
 ROUND((SUM(S.TOTALPRICE) - SUM(NVL(T.TAXSUM, 0))) /
       DECODE(SUM(S.QUANTITY), 0, NULL, SUM(S.QUANTITY)),
       1) AS price2 
  FROM 
  (SELECT T.ID AS locid ,
       T.ARTICLE AS article ,
       SUBSTR(T.MAX_DATA, 9) AS id ,
       TO_DATE(SUBSTR(T.MAX_DATA, 1, 8), 'YYYYMMDD') AS createdat 
  FROM (SELECT D.LOCATIONTO ID,
               S.ARTICLE,
               MAX(TO_CHAR(D.CREATEDAT, 'YYYYMMDD') || D.ID) MAX_DATA
          FROM --SUPERMAG.TTLOCPARENTLIST L,
               SUPERMAG.SMDOCUMENTS     D,
               SUPERMAG.SMSPEC          S
         WHERE D.DOCTYPE = S.DOCTYPE
           AND D.ID = S.DOCID
           AND L.PARENTID = D.LOCATIONTO
           AND D.DOCSTATE >= 3
           AND D.OPCODE = 0
           AND D.DOCTYPE = 'WI'
           AND D.CREATEDAT <= TO_DATE('20.12.2006', 'DD.MM.YYYY')
         GROUP BY D.LOCATIONTO, S.ARTICLE) T
 WHERE 1 = 1
  ) G, SUPERMAG.SMSPEC S, SUPERMAG.SMSPECTAX T
 WHERE 'WI' = S.DOCTYPE
   AND G.ID = S.DOCID
   AND G.ARTICLE = S.ARTICLE
   AND S.DOCTYPE = T.DOCTYPE(+)
   AND S.DOCID = T.DOCID(+)
   AND S.SPECITEM = T.SPECITEM(+)
 GROUP BY G.LOCID, G.ARTICLE
28.12.2007 10:14
isi
 
ну так тогда двойное сканирование таблицы получится
28.12.2007 10:20
Mtirt
 
Это похоже выдрано из стандартного супермажного отчета - остатки, с ценами последней поставки.
Так что все претензии по быстродействию к С+ :)
28.12.2007 10:30
isi
 
Да, по моему от туда и выдрано :)
04.02.2008 09:15
isi
 
Вообщем вот таким запросом можно быстро получить цену последнего прихода очень быстро:

select /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum
from (
select smdocuments.createdat, smdocuments.id, smdocuments.locationto , smspec.article, smspec.itemprice, smspec.quantity, smspec.totalprice
from smdocuments, smspec
WHERE smspec.doctype = smdocuments.doctype
AND smspec.docid = smspec.docid
AND smspec.article IN ('79290')
AND smdocuments.locationto IN (16)
and smdocuments.docstate in (2,3)
order by smdocuments.createdat desc
) a
where ROWNUM = 1
04.02.2008 09:45
kadr
 
Цитата:
isi Вообщем вот таким запросом можно быстро получить цену последнего прихода очень быстро:
на каких объёмах тестировалось? Быстро - это достаточно абстрактная величина, а если нужно получить последнюю цену для кучи (~10000) артикулов и нескольких МХ тоже быстро отрабатывает?
04.02.2008 10:01
isi
 
На центральной БД в 80 Гигов, запрос возвращает только первую запись, если надо для нескольких то его в место поля, попробуй, я сам удивился производительности, нашел реализацию у Том Кайт тут:
04.02.2008 14:21
kadr
 
Цитата:
select /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum
from (
select smdocuments.createdat, smdocuments.id, smdocuments.locationto , smspec.article, smspec.itemprice, smspec.quantity, smspec.totalprice
from smdocuments, smspec
WHERE smspec.doctype = smdocuments.doctype

AND smspec.docid = smspec.docid

а это зачем? какой тайный смысл
Цитата:
AND smspec.article IN ('79290')
AND smdocuments.locationto IN (16)
and smdocuments.docstate in (2,3)
order by smdocuments.createdat desc
) a
where ROWNUM = 1
04.02.2008 14:36
kadr
 
исходные данные

Код:
SELECT COUNT(*) FROM smdocuments
3856280
Код:
 select count(*) from smspec
159247539
вот немного переписанный запрос автора
Код:
SELECT /*+ FIRST_ROWS(n) */
 A.*, ROWNUM RNUM
  FROM (SELECT SMDOCUMENTS.CREATEDAT,
               SMDOCUMENTS.ID,
               SMDOCUMENTS.LOCATIONTO,
               SMSPEC.ARTICLE,
               SMSPEC.ITEMPRICE,
               SMSPEC.QUANTITY,
               SMSPEC.TOTALPRICE
          FROM SMDOCUMENTS, SMSPEC
         WHERE SMSPEC.DOCTYPE = SMDOCUMENTS.DOCTYPE
           AND SMDOCUMENTS.ID = SMSPEC.DOCID
           AND SMSPEC.ARTICLE IN ('18500')
           AND SMDOCUMENTS.LOCATIONTO IN (2015)
           AND SMDOCUMENTS.DOCSTATE IN (2, 3)
           AND SMDOCUMENTS.DOCTYPE='WI'
         ORDER BY SMDOCUMENTS.CREATEDAT DESC) A
 WHERE ROWNUM = 1
в период очччень хорошей загрузки базы
от 15 до 200 сек.

Код:
SELECT *
  FROM (SELECT A2.CREATEDAT,
               A2.ID,
               A2.LOCATIONTO,
               B2.ARTICLE,
               B2.ITEMPRICE,
               B2.QUANTITY,
               B2.TOTALPRICE,
               ROW_NUMBER() OVER(PARTITION BY B2.ARTICLE ORDER BY A2.CREATEDAT DESC) RN
          FROM SUPERMAG.SMDOCUMENTS A2, SUPERMAG.SMSPEC B2
         WHERE A2.DOCTYPE = B2.DOCTYPE
           AND A2.ID = B2.DOCID
           AND A2.DOCSTATE IN (2, 3)
           AND A2.LOCATIONTO IN (2015)
           AND A2.DOCTYPE = 'WI' -- определение последнего поставщика
           AND B2.ARTICLE IN ('18500'))
 WHERE RN = 1
в тот же период
от 0,01 до 5 секунд

P.S. аналитические функции у того же Кайта очень хорошо рассмотрены
04.02.2008 15:53
isi
 
собственно сейчас с аналитическими фнкциями и разбираюсь, базы под рукой нет сейчас, завтра выложу свою статистику, в моем варианте у меня ответ при любых условиях был сравним с реакцией интерфейса при одном но, если был хотя бы один приход по мх+артикул, если же прихода не было, то ответ доходил до 30 сек
04.02.2008 16:27
kadr
 
Цитата:
isi в моем варианте у меня ответ при любых условиях был сравним с реакцией интерфейса при одном но, если был хотя бы один приход по мх+артикул, если же прихода не было, то ответ доходил до 30 сек

1. при использовании интерфейса СМ генерится куча рекурсивных запроосов, значит нам надо стремиться чтобы работало быстрее.

2. если у меня прихода не было, то твой вариант всё-равно выдавал строки
04.02.2008 23:10
mighty
 
Если в конструкцию ROW_NUMBER() OVER (PARTITION BY B2.ARTICLE ORDER BY A2.CREATEDAT DESC) RN
добавить A2.LOCATIONTO то можно заремить отбор по месту хранения и получать последние закупочные цены по одному товару по всем местам хранения
ROW_NUMBER() OVER (PARTITION BY A2.LOCATIONTO,B2.ARTICLE ORDER BY A2.CREATEDAT DESC) RN

И еще важно отсекать оприходование недостачи, то есть добавить условие A2.OPCODE=0

Итого:
SELECT *
FROM (SELECT A2.CREATEDAT,
A2.ID,
A2.LOCATIONTO,
B2.ARTICLE,
B2.ITEMPRICE,
B2.QUANTITY,
B2.TOTALPRICE,
ROW_NUMBER() OVER (PARTITION BY A2.LOCATIONTO,B2.ARTICLE ORDER BY A2.CREATEDAT DESC) RN
FROM SUPERMAG.SMDOCUMENTS A2, SUPERMAG.SMSPEC B2
WHERE A2.DOCTYPE = B2.DOCTYPE
AND A2.ID = B2.DOCID
AND A2.DOCSTATE IN (2, 3)
AND A2.OPCODE=0
-- AND A2.LOCATIONTO IN (2015)
AND A2.DOCTYPE = 'WI' -- определение последнего поставщика
AND B2.ARTICLE IN ('18500'))
WHERE RN = 1
05.02.2008 03:07
isi
 
Ну вот видете вместе получилось довести до ума запрос, который многим начинающим нужен :)
05.02.2008 03:29
isi
 
Цитата:
kadr 1. при использовании интерфейса СМ генерится куча рекурсивных запроосов, значит нам надо стремиться чтобы работало быстрее.
Я не про интерфейс СМ, имелось ввиду результат в пределах ответа от сер
Цитата:
kadr 2. если у меня прихода не было, то твой вариант всё-равно выдавал строки
Это как это?
05.02.2008 07:44
kadr
 
Цитата:
mighty Если в конструкцию ROW_NUMBER() OVER (PARTITION BY B2.ARTICLE ORDER BY A2.CREATEDAT DESC) RN
добавить A2.LOCATIONTO то можно заремить отбор по месту хранения и получать последние закупочные цены по одному товару по всем местам хранения
ROW_NUMBER() OVER (PARTITION BY A2.LOCATIONTO,B2.ARTICLE ORDER BY A2.CREATEDAT DESC) RN

И еще важно отсекать оприходование недостачи, то есть добавить условие A2.OPCODE=0
в оригинале запроса так и было, кажется его уже выкладывали мы, и вроде не один раз.
но что было написано автором, то и преобразовывалось, а фильтр по операциям это уже частный случай
05.02.2008 07:47
kadr
 
Цитата:
isi Я не про интерфейс СМ, имелось ввиду результат в пределах ответа от сер
поэтому я и просил определение для понятия "быстро", ибо в периоды простоя сервера разница в скорости выполнения не очень заметна, а вот во время активной работы это уже видно
Цитата:
Это как это?
я тоже очень удивился и показывал тебе строку в твоём запросе, которая приводит к такому результату
Опции темы


Часовой пояс GMT +3, время: 00:44.

 

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