03.02.2010 02:24
YuraZ
 
Привет.
Предлагаю, заинтересованным, разминку для ума. Подобного рода задачи на sql.ru называт "пятничными" :) Так или иначе, многие с подобного рода задачами салкиваются. Как правило, решение тоже, так или иначе работает :) Но хотелось бы, получить наиболее "красивое" решение, с применением именно "изюминок" Oracle. Сразу скажу, что у меня нет более-менее красивого решения этой задачи. Но хочется, с вашей помощью, его найти. И так, давайте попробуем.
Имеем таблицу вида:
Код:
ARTICLE   DATE         PRICE
000001    01.01.2006   100
000001    01.01.2007   200
000001    01.01.2008   300
000001    01.01.2009   400
000001    01.01.2010   500
000002    01.01.2006   100
000002    01.01.2007   200
000002    01.01.2008   150
000002    01.01.2009   220
000002    01.01.2010   210
Необходимо отобрать по каждоум артикулу ОДНИМ запросом последнюю цену. Не максимальную, а имено последнюю.
Для желающих попробовать, вот код:
Код:
CREATE TABLE YZTEST(
  ARTICLE  VARCHAR2(50) NOT NULL,
  ARTDATE  DATE NOT NULL,
  PRICE    NUMBER(14, 2))
/

INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000001', TO_DATE('01.01.2006', 'DD.MM.YYYY'), 100);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000001', TO_DATE('01.01.2007', 'DD.MM.YYYY'), 200);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000001', TO_DATE('01.01.2008', 'DD.MM.YYYY'), 300);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000001', TO_DATE('01.01.2009', 'DD.MM.YYYY'), 400);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000001', TO_DATE('01.01.2010', 'DD.MM.YYYY'), 500);

INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000002', TO_DATE('01.01.2006', 'DD.MM.YYYY'), 100);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000002', TO_DATE('01.01.2007', 'DD.MM.YYYY'), 200);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000002', TO_DATE('01.01.2008', 'DD.MM.YYYY'), 150);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000002', TO_DATE('01.01.2009', 'DD.MM.YYYY'), 220);
INSERT INTO YZTEST(ARTICLE, ARTDATE, PRICE) VALUES('000002', TO_DATE('01.01.2010', 'DD.MM.YYYY'), 210);
Вбиваем его в тот же SQL Navigator (я пользовался именно им), и пробуем сделать выборку.
03.02.2010 08:59
OlegON
 
Сделать процедурку и ею потом пользоваться, это "один запрос"? В противном случае решение "одним запросом" выливается в такие безумные сортировки, что никакого ТЕМПа не хватает при большом количестве артикулов. ИМХО.
Цель "одного запроса"?
03.02.2010 09:24
twix
 
Цитата:
OlegON Сделать процедурку и ею потом пользоваться, это "один запрос"? В противном случае решение "одним запросом" выливается в такие безумные сортировки, что никакого ТЕМПа не хватает при большом количестве артикулов. ИМХО.
Цель "одного запроса"?
тут важна не причина, а процесс и варианты решений.
пятничная задачка совсем не обязательно должна иметь практическую пользу (8
03.02.2010 09:27
Requin
 
Один из вариантов применение псевдостолбца ROWNUM
Код:
SELECT *
    FROM
        (SELECT *
            FROM YZTEST
            WHERE ARTICLE = 'Требуемый_Артикул'
            ORDER BY ARTDATE DESC)
 WHERE
    ROWNUM < 2
03.02.2010 09:28
Mtirt
 
Угу, только у тебя 2 запроса, один вложен в другой.
03.02.2010 09:46
MirProd
 
Код:
select article, max(price) keep (dense_rank last order by artdate) lprice
from yztest
group by article
03.02.2010 11:03
Requin
 
Еще один вариант есть.

Код:
SELECT DISTINCT article, FIRST_VALUE(price) OVER(PARTITION BY article ORDER BY artdate DESC) lprice
FROM yztest
03.02.2010 17:52
YuraZ
 
Цитата:
MirProd
Код:
select article, max(price) keep (dense_rank last order by artdate) lprice
from yztest
group by article
Цитата:
Requin Еще один вариант есть.

Код:
SELECT DISTINCT article, FIRST_VALUE(price) OVER(PARTITION BY article ORDER BY artdate DESC) lprice
FROM yztest
Лихо.
Протестировал на базе магазина работающего примерно год, ~10 касс, 22.000 карточек. Отбирал цену без налогов из приходных накладных. Запрос от MirProd отрабатывает за 2.8 с, запрос от Requin отрабатывает за 5с.
Часовой пояс GMT +3, время: 15:53.

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