Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Можно ли упростить запрос (first_value, только для агрегации) / 12 сообщений из 12, страница 1 из 1
07.12.2020, 16:17
    #40025320
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
Есть таблица slices, в которой несколько раз в день (moment) фиксируются некие значения (value).
Нужно получить набор значений на начало дня (точнее самые первые значения в текущих сутках).
Делаю примерно так:
Код: plsql
1.
2.
3.
4.
5.
6.
  select item_id
  , min(moment) as moment
  , min(value) keep (dense_rank first order by moment) as value
  from slices
  where moment >= trunc(sysdate)
  group by item_id


Но в реальном запросе этих value у меня довольно много.
Я для каждого повторяю min(...) keep (dense_rank first order by moment).
А можно упростить?
...
Рейтинг: 0 / 0
07.12.2020, 16:24
    #40025324
PuM256
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
А что в текущем варианте не устраивает?
...
Рейтинг: 0 / 0
07.12.2020, 18:57
    #40025387
Щукина Анна
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
Alibek B.,

Соседний топик посетите....
...
Рейтинг: 0 / 0
07.12.2020, 20:13
    #40025410
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
Спасибо.
Не нравилось много однотипных строк, думал можно улучшить.
...
Рейтинг: 0 / 0
07.12.2020, 20:38
    #40025418
Щукина Анна
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
Alibek B.,

а сервер у вас какой версии?
Начиная с 12С, должно работать такое:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
with 
  t (id, dt, txt) as 
    (
      select 1, date'2020-12-01', 'name1_1' from dual union all
      select 1, date'2020-12-02', 'name1_2' from dual union all
      select 1, date'2020-12-03', 'name1_3' from dual union all
      select 2, date'2020-12-01', 'name2_1' from dual union all
      select 2, date'2020-12-02', 'name2_2' from dual
    )
select *
  from t
  order by row_number() over(partition by id order by dt desc)
  fetch first 1 rows with ties;
...
Рейтинг: 0 / 0
07.12.2020, 21:19
    #40025422
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
Мне такое решение очень нравится.
Есть ли у него подводные камни для большого числа ties?
...
Рейтинг: 0 / 0
07.12.2020, 21:35
    #40025424
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
НеофитSQL
Мне такое решение очень нравится.
Есть ли у него подводные камни для большого числа ties?


Если посмотреть (через DBMS_UTILITY.EXPAND_SQL_TEXT) то под капотом банальный:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
with 
  t (id, dt, txt) as 
    (
      select 1, date'2020-12-01', 'name1_1' from dual union all
      select 1, date'2020-12-02', 'name1_2' from dual union all
      select 1, date'2020-12-03', 'name1_3' from dual union all
      select 2, date'2020-12-01', 'name2_1' from dual union all
      select 2, date'2020-12-02', 'name2_2' from dual
    ),
  x as (
        select  t.*,
                row_number() over(partition by id order by dt desc) rn
          from  t
       )
select  id, dt, txt
  from  x
  where rn <= 1
/



SY.
...
Рейтинг: 0 / 0
07.12.2020, 21:37
    #40025425
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
SY,

Спасибо, очень полезная штука.
...
Рейтинг: 0 / 0
07.12.2020, 21:42
    #40025427
andreymx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
SY
Если посмотреть (через DBMS_UTILITY.EXPAND_SQL_TEXT) то под капотом банальный:
если бы ОНИ алиас поля в групп бай еще разрешили использовать
...
Рейтинг: 0 / 0
07.12.2020, 22:41
    #40025436
SY
SY
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
Кстати:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create table t as
with 
  t (id, dt, txt, z) as 
    (
      select 1, date'2020-12-01', 'name1_1',0 from dual union all
      select 1, date'2020-12-02', 'name1_2',0 from dual union all
      select 1, date'2020-12-03', 'name1_3',1 from dual union all
      select 2, date'2020-12-01', 'name2_1',0 from dual union all
      select 2, date'2020-12-02', 'name2_2',1 from dual
    )
select * from t
/




Через fetch first:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select t.*,
       1 / z
  from t
  order by row_number() over(partition by id order by dt desc)
  fetch first 1 rows with ties
/
       1 / z
         *
ERROR at line 2:
ORA-01476: divisor is equal to zero


SQL>




Без fetch first:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
with x as (
           select  t.*,
                   1 / z zz,
                   row_number() over(partition by id order by dt desc) rn
             from  t
          )
select  *
  from  x
  where rn <= 1
/

        ID DT        TXT              Z         ZZ         RN
---------- --------- ------- ---------- ---------- ----------
         1 03-DEC-20 name1_3          1          1          1
         2 02-DEC-20 name2_2          1          1          1

SQL>



Почему:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
SQL> explain plan for
  2  select t.*,
  3         1 / z
  4    from t
  5    order by row_number() over(partition by id order by dt desc)
  6    fetch first 1 rows with ties
  7  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2991172602

---------------------------------------------------------------------------------
| Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |      |     5 |   415 |     5  (40)| 00:00:01 |
|*  1 |  VIEW                    |      |     5 |   415 |     5  (40)| 00:00:01 |
|*  2 |   WINDOW SORT PUSHED RANK|      |     5 |   350 |     5  (40)| 00:00:01 |
|   3 |    VIEW                  |      |     5 |   350 |     4  (25)| 00:00:01 |
|   4 |     WINDOW SORT          |      |     5 |   105 |     4  (25)| 00:00:01 |
|   5 |      TABLE ACCESS FULL   | T    |     5 |   105 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("from$_subquery$_003"."rowlimit_$$_rank"<=1)
   2 - filter(RANK() OVER ( ORDER BY
              "from$_subquery$_002"."rowlimit_$_0")<=1)

19 rows selected.

SQL> explain plan for
  2  with x as (
  3             select  t.*,
  4                     1 / z zz,
  5                     row_number() over(partition by id order by dt desc) rn
  6               from  t
  7            )
  8  select  *
  9    from  x
 10    where rn <= 1
 11  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3047187157

---------------------------------------------------------------------------------
| Id  | Operation                | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |      |     5 |   350 |     4  (25)| 00:00:01 |
|*  1 |  VIEW                    |      |     5 |   350 |     4  (25)| 00:00:01 |
|*  2 |   WINDOW SORT PUSHED RANK|      |     5 |   105 |     4  (25)| 00:00:01 |
|   3 |    TABLE ACCESS FULL     | T    |     5 |   105 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN"<=1)
   2 - filter(ROW_NUMBER() OVER ( PARTITION BY "ID" ORDER BY
              INTERNAL_FUNCTION("DT") DESC )<=1)

17 rows selected.

SQL>



Так-что доверяй но проверяй.

SY.
...
Рейтинг: 0 / 0
07.12.2020, 23:55
    #40025439
НеофитSQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
andreymx,

MySql по-моему это умеет, но не забудут ли кодеры что select вычисляется после group by?

Код: plsql
1.
2.
3.
Select count(*) cnt 
  from TBL
 group by cnt
...
Рейтинг: 0 / 0
08.12.2020, 00:11
    #40025444
andreymx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Можно ли упростить запрос (first_value, только для агрегации)
НеофитSQL
andreymx,

MySql по-моему это умеет, но не забудут ли кодеры что select вычисляется после group by?

Код: plsql
1.
2.
3.
Select count(*) cnt 
  from TBL
 group by cnt

ужас на крыльях ночи
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Можно ли упростить запрос (first_value, только для агрегации) / 12 сообщений из 12, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]