помогите составить SQL запросик(Oracle)
select max(a) from table
group by b,c
Сто лет уже не писал запросы, надеюсь не напутал.
group by b,c
Сто лет уже не писал запросы, надеюсь не напутал.
Думаю имелось в виду:
select b, c from (
select b, c, row_number over (partition by b, c order by a desc) rn from table
) where rn = 1;
ЗЫ
select b, c from (
select b, c, row_number over (partition by b, c order by a desc) rn from table
) where rn = 1;
ЗЫ
Ксожалению, есть еще поля кроме a,b u c =(
Подобные мысли у меня тоже были, но суть в том, что сам запрос немаленький, много полей, сложные условия фильтрации, хотелось что нить совсем простое )
много полейпоставь в селектах звёздочки

навскидку знаю 3 варианта
первый ты сам назвал:
ещё два используют аналитические функции (Update: выше уже привели их):
здесь d, e - просто некие поля, которые не используются для группировки, но их тоже требуется извлечь запросом.
первый ты сам назвал:
выборки максимально значения поля a в подзапросе и фильтрации по нему
SELECT t.a AS a,
t.b AS b,
t.c AS c,
t.e AS d,
t.d AS e
FROM tab t,
(SELECT MAX (a b, c FROM tab GROUP BY b, c) maxt
WHERE t.a = maxt.a AND
t.b = maxt.b AND
t.c = maxt.c AND
<нужные тебе условия>
ещё два используют аналитические функции (Update: выше уже привели их):
SELECT *
FROM (
SELECT t.a AS a,
t.b AS b,
t.c AS c,
t.d AS d,
t.e AS e,
ROW_NUMBER OVER (PARTITION BY t.b, t.c ORDER BY t.a DESC) AS rn
FROM tab t
WHERE <нужные тебе условия> )
WHERE rn = 1
SELECT MAX(t.a) AS a,
t.b AS b,
t.c AS c,
MAX (t.d) KEEP (DENSE_RANK LAST ORDER BY t.a) AS d,
MAX (t.e) KEEP (DENSE_RANK LAST ORDER BY t.a) AS e
<и так для всех полей, которые просто надо извлечь (т.е. без группировки по ним)>
FROM tab t
WHERE
<нужные тебе условия>
GROUP BY t.b, t.c
здесь d, e - просто некие поля, которые не используются для группировки, но их тоже требуется извлечь запросом.
наверняка для нее есть какие то простые методы (кроме выборки максимально значения поля a в подзапросе и фильтрации по нему)Есть, но используют аналитические функции. Что проще - фиг знает, по мне так проще без них
А вот про производительность разных вариантов ничего сказать не могу к сожалению
Знаю только, что два варианта с аналитическими функциями, приведённые мною выше - одинаковы. А вот как они в сравнении с выборкой максимального значения в подзапросе - не знаю.
Я постил ссылку на старую тему.
Там zafhoz говорил, что в 1,5 раза быстрее у него получилось.
Там zafhoz говорил, что в 1,5 раза быстрее у него получилось.
да, говорил
но я из той темы:
1) так и не понял, в 1.5 раза быстрее чем что?
2) не видел планов исполнения запросов
3) не видел индексов
но я из той темы:
1) так и не понял, в 1.5 раза быстрее чем что?
2) не видел планов исполнения запросов
3) не видел индексов
пока что мне нравится больше всего второй вариант, но есть два вопроса :
1) что за ROW_NUMBER
2) Что за keep в третьем варианте
1) что за ROW_NUMBER
2) Что за keep в третьем варианте
есть два вопроса :http://download-east.oracle.com/docs/cd/B19306_01/server.102...
1) что за ROW_NUMBER
2) Что за keep в третьем вариантеhttp://www.ss64.com/orasyntax/an_firstlast.html
никого ещё не смущает, что второй и третий варианты выдают разные результаты?
ща проверю 

CREATE TABLE TAB
(
id NUMBER NOT NULL,
a DATE NOT NULL,
b CHAR(1) NOT NULL,
c CHAR(1) NOT NULL,
d VARCHAR2(16
e VARCHAR2(16)
);
ALTER TABLE TAB ADD (CONSTRAINT TAB_PK PRIMARY KEY (id;
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (1, TO_Date( '06/20/2007 02:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '1', '1', 'abc', 'def');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (2, TO_Date( '06/19/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '1', '1', 'qaz', 'wsx');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (3, TO_Date( '06/21/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '1', '1', 'rfd', 'rfv');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (4, TO_Date( '06/06/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '2', '1', 'ert', 'dfg');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (5, TO_Date( '06/02/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '2', '2', 'ert', 'ddf');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (6, TO_Date( '06/05/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '1', '2', 'rft', 'dfg');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (7, TO_Date( '06/03/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '2', '1', 'cvb', 'pl,');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (8, TO_Date( '06/15/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '2', '2', 'cvb', 'kjh');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (9, TO_Date( '06/25/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '1', '2', 'cvb', 'zxc');
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (10, TO_Date( '06/11/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '2', '1', 'plm', 'okm');
COMMIT;
SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY/MM/DD';
Session altered.
SQL> SELECT *
2 FROM tab t
3 ORDER BY t.b, t.c, t.id;
ID A B C D E
---------- ---------- - - ---------------- ----------------
1 2007/06/20 1 1 abc def
2 2007/06/19 1 1 qaz wsx
3 2007/06/21 1 1 rfd rfv
6 2007/06/05 1 2 rft dfg
9 2007/06/25 1 2 cvb zxc
4 2007/06/06 2 1 ert dfg
7 2007/06/03 2 1 cvb pl,
10 2007/06/11 2 1 plm okm
5 2007/06/02 2 2 ert ddf
8 2007/06/15 2 2 cvb kjh
10 rows selected.
SQL> SELECT t.id AS id,
2 t.a AS a,
3 t.b AS b,
4 t.c AS c,
5 t.d AS d,
6 t.e AS e
7 FROM tab t,
8 (SELECT MAX(a) a, b, c FROM tab GROUP BY b, c) tmax
9 WHERE t.a = tmax.a AND
10 t.b = tmax.b AND
11 t.c = tmax.c
12 ORDER BY b,c;
ID A B C D E
---------- ---------- - - ---------------- ----------------
3 2007/06/21 1 1 rfd rfv
9 2007/06/25 1 2 cvb zxc
10 2007/06/11 2 1 plm okm
8 2007/06/15 2 2 cvb kjh
SQL> SELECT *
2 FROM (
3 SELECT t.id AS id,
4 t.a AS a,
5 t.b AS b,
6 t.c AS c,
7 t.d AS d,
8 t.e AS e,
9 ROW_NUMBER OVER (PARTITION BY t.b, t.c ORDER BY t.a DESC) AS rn
10 FROM tab t
11 )
12 WHERE rn = 1
13 ORDER BY b,c;
ID A B C D E RN
---------- ---------- - - ---------------- ---------------- ----------
3 2007/06/21 1 1 rfd rfv 1
9 2007/06/25 1 2 cvb zxc 1
10 2007/06/11 2 1 plm okm 1
8 2007/06/15 2 2 cvb kjh 1
SQL> SELECT MAX (t.id) KEEP (DENSE_RANK LAST ORDER BY t.a) AS id,
2 MAX(t.a) AS a,
3 t.b AS b,
4 t.c AS c,
5 MAX (t.d) KEEP (DENSE_RANK LAST ORDER BY t.a) AS d,
6 MAX (t.e) KEEP (DENSE_RANK LAST ORDER BY t.a) AS e
7 FROM tab t
8 GROUP BY t.b, t.c
9 ORDER BY t.b, t.c;
ID A B C D E
---------- ---------- - - ---------------- ----------------
3 2007/06/21 1 1 rfd rfv
9 2007/06/25 1 2 cvb zxc
10 2007/06/11 2 1 plm okm
8 2007/06/15 2 2 cvb kjh
что не так?
del
Т.е.
INSERT INTO TAB ( ID, A, B, C, D, E ) VALUES (11, TO_Date( '06/21/2007 12:00:00 AM', 'MM/DD/YYYY HH:MI:SS AM' '1', '1', 'rfv', 'rfd');
к счастью, в условии задачи (см. первый пост) есть ограничение

с различными значениям поля a

Понятно. Меня смутила фраза про одинаковость:
Знаю только, что два варианта с аналитическими функциями, приведённые мною выше - одинаковы. А вот как они в сравнении с выборкой максимального значения в подзапросе - не знаю.
Кстати, а где в оракловой документации SQLной есть что-нибудь про keep?
Про DENSE_RANK нашел, а про keep нет
Про DENSE_RANK нашел, а про keep нет
Оставить комментарий
wwoland
Пусть есть таблица с полями a,b,cвыборка идет по полям c и b, допустим.
Некоторым значениям c и b соответствует много записей с различными значениям поля a.
Нужно выбрать из них запись с максимальным значением поля a.
Какое простейшее решение этой задачи.
Она довольно стандартная, навернякак для нее есть какие то простые методы(кроме выборки максимально значения поля a в подзапросе и фильтрации по нему)