Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / получение последних записей из таблицы / 18 сообщений из 18, страница 1 из 1
23.11.2016, 14:28
    #39352741
Mr.Fontaine
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Доброе время суток, сообщество!
Есть задача: вывести информацию о записях, произведённых за последние сутки, но если за сутки было сделано меньше минимально допустимого количества записей, то выводить минимально допустимое количество записей.
Организовал двумя запросами:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select count(*) into v_amount_rec 
from (select m_field, max(s_field) as s_field from table_LoadInfo where s_field>sysdate-1 group by m_field)

v_result_amount = case when v_amount_rec > 10 then v_amount_rec else 10 end
              
select * 
from (select m_field, max(s_field) as s_field from table_LoadInfo group by m_field order by 2 desc) 
where rownum <= v_result_amount


Видно, что оба запроса похожи друг на друга, поэтому возник вопрос, а можно ли это сделать одним запросом?
Думаю, может connect by как-то прикрутить сюда, но не понимаю как...
...
Рейтинг: 0 / 0
23.11.2016, 16:03
    #39352819
env
env
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
т.е. вся задача - просто вывести последние N записей из запроса?
...
Рейтинг: 0 / 0
23.11.2016, 16:36
    #39352863
Glays
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Mr.Fontaine,
например так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SELECT *
  FROM (SELECT t_L.*,
               RANK ()
               OVER (
                  ORDER BY
                     CASE
                        WHEN s_field > (SYSDATE - 1) THEN TRUNC (s_field)
                        ELSE s_field
                     END DESC,
                     CASE WHEN s_field > (SYSDATE - 1) THEN 0 ELSE ROWNUM END)
                  r_k
          FROM (  SELECT m_field, MAX (s_field) AS s_field
                    FROM table_LoadInfo
                GROUP BY m_field) t_L)
 WHERE r_k <= 10
...
Рейтинг: 0 / 0
23.11.2016, 16:52
    #39352876
Fogel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
GlaysMr.Fontaine,
например так
Код: plsql
1.
2.
3.
...
    RANK ()
...


лучше DENSE_RANK
...
Рейтинг: 0 / 0
23.11.2016, 17:02
    #39352882
Fogel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
GlaysMr.Fontaine,
например так
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SELECT *
  FROM (SELECT t_L.*,
               RANK ()
               OVER (
                  ORDER BY
                     CASE
                        WHEN s_field > (SYSDATE - 1) THEN TRUNC (s_field)
                        ELSE s_field
                     END DESC,
                     CASE WHEN s_field > (SYSDATE - 1) THEN 0 ELSE ROWNUM END)
                  r_k
          FROM (  SELECT m_field, MAX (s_field) AS s_field
                    FROM table_LoadInfo
                GROUP BY m_field) t_L)
 WHERE r_k <= 10


насколько я понял поставленную задачу, нужно выводить все строки (сколько бы их не было) за последние сутки, если их кол-во больше порога (в данном случае 10).
если меньше, то нужно просто вывести 10 строк последних, то есть выборка идёт дальше в прошлое, а не только за последние сутки.
если так, то этот запрос хоть с rank, хоть с dense_rank не подходит.
...
Рейтинг: 0 / 0
23.11.2016, 18:01
    #39352938
Glays
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Fogel,
пофиксил потерянную часть суток
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
WITH table_LoadInfo
     AS (    SELECT LEVEL AS m_field, SYSDATE - (.04 * LEVEL) AS s_field
               FROM DUAL
         CONNECT BY LEVEL < 50)
SELECT *
  FROM (SELECT t_L.*,
               RANK ()
               OVER (
                  ORDER BY
                     CASE
                        WHEN s_field >= (SYSDATE - 1) THEN TRUNC (SYSDATE)
                        ELSE s_field
                     END DESC,
                     CASE
                        WHEN s_field >= (SYSDATE - 1) THEN 0
                        ELSE ROWNUM
                     END)
                  r_k
          FROM (  SELECT m_field, MAX (s_field) AS s_field
                    FROM table_LoadInfo
                GROUP BY m_field) t_L)
 WHERE r_k <= 10
 order by s_field desc
...
Рейтинг: 0 / 0
23.11.2016, 18:18
    #39352955
Fogel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Glays
Код: plsql
1.
2.
3.
4.
5.
....
 (  SELECT m_field, MAX (s_field) AS s_field
                    FROM table_LoadInfo
                GROUP BY m_field)
....


а если в таблице миллиард строк, для получения нескольких верхних строк все равно будешь всю таблицу агрегировать?
...
Рейтинг: 0 / 0
23.11.2016, 18:50
    #39352987
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Mr.Fontaine,
влоб
Код: 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.
WITH table_LoadInfo
     AS (
    SELECT 1 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 2 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 5 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 6 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 7 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 8 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 9 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 10 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 11 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-4 AS s_field FROM DUAL 
)
SELECT *
  FROM (SELECT t_L.*,
               SUM(CASE WHEN s_field >= (SYSDATE - 1) THEN 1 ELSE 0 END) 
               OVER () r_k --к-во за сутку
        FROM (  SELECT m_field, MAX (s_field) AS s_field
                FROM table_LoadInfo
                GROUP BY m_field) t_L
        ORDER BY s_field desc 
)
 WHERE r_k > 10 or (r_k<=10 and rownum<=10)
order by 1
/

SQL> /

   M_FIELD S_FIELD         R_K
---------- -------- ----------
         1 23.11.16          8
         2 23.11.16          8
         3 23.11.16          8
         4 23.11.16          8
         5 23.11.16          8
         6 23.11.16          8
         7 23.11.16          8
         8 23.11.16          8
         9 20.11.16          8
        10 20.11.16          8

10 rows selected.



ps
но нужно ли группировать по всей таблице

.....
stax
...
Рейтинг: 0 / 0
23.11.2016, 18:52
    #39352990
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
FogelGlays
Код: plsql
1.
2.
3.
4.
5.
....
 (  SELECT m_field, MAX (s_field) AS s_field
                    FROM table_LoadInfo
                GROUP BY m_field)
....


а если в таблице миллиард строк, для получения нескольких верхних строк все равно будешь всю таблицу агрегировать?
в исходном посте мистер тож миллиард строк группирует

.....
stax
...
Рейтинг: 0 / 0
23.11.2016, 20:41
    #39353060
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
stax..FogelОн троллирует таких, как ты.
...
Рейтинг: 0 / 0
23.11.2016, 21:41
    #39353084
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Elicstax..пропущено...
Он троллирует таких, как ты.
не понял
я ж старался

.....
stax
...
Рейтинг: 0 / 0
23.11.2016, 22:14
    #39353107
ora601
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Mr.Fontaine,

Если тебе нужно TOP-N по группе, то ищи по этим кейвордам. Там есть два решения - через аналитику (row_number() over (partition by group_id order by time desc) ) которое дольше и рекурсивный вариант.
...
Рейтинг: 0 / 0
24.11.2016, 08:29
    #39353317
Fogel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
stax..Elicпропущено...
Он троллирует таких, как ты.
не понял
я ж старался
stax, не принимайте близко к сердцу. Elic зачастую изрядно желчен.

Относительно группировки по всему объёму - сразу подумал, что это не комильфо, собственно поэтому своего решения и не написал (хотя и заглянул сюда в кои-то веки), т.к. отбор первых n строк подразумевает сортировку, а сортировка - выборку полного набора, то есть в данном случае группировку по всей массе, поэтому в лоб решать, применяя вначале агрегат, потому сортировку - это канонично, но на больших объёмах тяжело.
поэтому я бы действовал точно не в лоб: кода больше, но на громадных объёмах быстрее. есть мысль насчёт алгоритма, надо его только выразить...
...
Рейтинг: 0 / 0
24.11.2016, 08:45
    #39353331
Fogel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
PS: относительно троллинга, насколько помню, фраза относилась к снобам, которые "набор знаний" считают заменой ума.
то есть тех, кто встречает по "одёжке" в виде этих самых знаний и тычет в RTFM каждому встречному.
просто не люблю снобов, тем более не очень умных, хотя и весьма образованных.
...
Рейтинг: 0 / 0
24.11.2016, 14:05
    #39353647
Mr.Fontaine
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
stax..Mr.Fontaine,
влоб
Код: 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.
WITH table_LoadInfo
     AS (
    SELECT 1 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 2 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 5 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 6 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 7 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 8 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 9 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 10 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 11 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-4 AS s_field FROM DUAL 
)
SELECT *
  FROM (SELECT t_L.*,
               SUM(CASE WHEN s_field >= (SYSDATE - 1) THEN 1 ELSE 0 END) 
               OVER () r_k --к-во за сутку
        FROM (  SELECT m_field, MAX (s_field) AS s_field
                FROM table_LoadInfo
                GROUP BY m_field) t_L
        ORDER BY s_field desc 
)
 WHERE r_k > 10 or (r_k<=10 and rownum<=10)
order by 1
/

SQL> /

   M_FIELD S_FIELD         R_K
---------- -------- ----------
         1 23.11.16          8
         2 23.11.16          8
         3 23.11.16          8
         4 23.11.16          8
         5 23.11.16          8
         6 23.11.16          8
         7 23.11.16          8
         8 23.11.16          8
         9 20.11.16          8
        10 20.11.16          8

10 rows selected.



ps
но нужно ли группировать по всей таблице

.....
stax
Спасибо, что навёл на мысль.
В итоге получилось проще:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
     SELECT t_L.* 
     FROM (
          SELECT m_field, MAX (s_field) AS s_field, SUM(CASE WHEN max(s_field) >= (SYSDATE-1) THEN 1 ELSE 0 END) OVER () r_k
          FROM table_LoadInfo
          GROUP BY m_field
          ORDER BY s_field desc
     ) t_L
     where rownum<=(case when r_k<10 then 10 else r_k end)


Про группировку всей таблицы.... Дело в том, что я, к сожалению, не придумал какой where тут поставить.
Суть в том, что m_field - грубо говоря, идентификатор заказа, s_field - время корректировки заказа. Заказ могут править несколько раз на дню, а могут и пару раз за неделю корректировку производить.
То есть твои данные могут иметь вид
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    SELECT 1 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-0.1 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-0.2 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-0.4 AS s_field FROM DUAL union all
    SELECT 2 AS m_field, SYSDATE-0.33 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-0.5 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-1.44 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-2.25 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-4.8 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-7.5 AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE-1 AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE-2 AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 5 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 6 AS m_field, SYSDATE-1.2 AS s_field FROM DUAL union all
    SELECT 7 AS m_field, SYSDATE-0.6 AS s_field FROM DUAL union all
    SELECT 8 AS m_field, SYSDATE-0.7 AS s_field FROM DUAL union all
    SELECT 9 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 10 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 11 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-4 AS s_field FROM DUAL 


Поэтому и делам группировку, определяя максимальную дату редактирования заказа. таблица table_LoadInfo - своеобразный лог корректировок информации о заказе (а точнее, загрузок в БД, ибо на своём компьютере пользователь может сколько угодно раз изменять параметры и производить расчёты и только потом приемлемый результат загрузить в базу).
Требуется вывести список заказов, которые были изменены в течении последних суток, но чтобы табличка в форме по понедельникам не была пустой решили в случае отсутствия корректировок выводить последние 10 изменённых заказов. То есть изначально непонятно, сколько строк выбирать из таблицы, чтобы произвести группировку.
Если подскажешь какое условие поставить чтобы группировать только часть информации из таблицы (понятно, что большинство заказов давно не используются и вытаскивать их при группировке каждый раз смысла нет)

P.S. Кстати, значения "одни сутки" и "минимум 10 заказов" могут меняться, в процедуре, в которой находится данный запрос они заданы как входные параметры, потому на цифрах sysdate-1 и rownum<=10 можно не зацикливаться, ставить любые значения
...
Рейтинг: 0 / 0
24.11.2016, 15:34
    #39353792
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Mr.FontaineСпасибо, что навёл на мысль.
В итоге получилось проще:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
     SELECT t_L.* 
     FROM (
          SELECT m_field, MAX (s_field) AS s_field, SUM(CASE WHEN max(s_field) >= (SYSDATE-1) THEN 1 ELSE 0 END) OVER () r_k
          FROM table_LoadInfo
          GROUP BY m_field
          ORDER BY s_field desc
     ) t_L
     where rownum<=(case when r_k<10 then 10 else r_k end)


Про группировку всей таблицы.... Дело в том, что я, к сожалению, не придумал какой where тут поставить.
Суть в том, что m_field - грубо говоря, идентификатор заказа, s_field - время корректировки заказа. Заказ могут править несколько раз на дню, а могут и пару раз за неделю корректировку производить.
То есть твои данные могут иметь вид
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
    SELECT 1 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-0.1 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-0.2 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-0.4 AS s_field FROM DUAL union all
    SELECT 2 AS m_field, SYSDATE-0.33 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-0.5 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-1.44 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-2.25 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-4.8 AS s_field FROM DUAL union all
    SELECT 3 AS m_field, SYSDATE-7.5 AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE-1 AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE-2 AS s_field FROM DUAL union all
    SELECT 4 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 5 AS m_field, SYSDATE AS s_field FROM DUAL union all
    SELECT 6 AS m_field, SYSDATE-1.2 AS s_field FROM DUAL union all
    SELECT 7 AS m_field, SYSDATE-0.6 AS s_field FROM DUAL union all
    SELECT 8 AS m_field, SYSDATE-0.7 AS s_field FROM DUAL union all
    SELECT 9 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 10 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 11 AS m_field, SYSDATE-3 AS s_field FROM DUAL union all
    SELECT 1 AS m_field, SYSDATE-4 AS s_field FROM DUAL 


Поэтому и делам группировку, определяя максимальную дату редактирования заказа. таблица table_LoadInfo - своеобразный лог корректировок информации о заказе (а точнее, загрузок в БД, ибо на своём компьютере пользователь может сколько угодно раз изменять параметры и производить расчёты и только потом приемлемый результат загрузить в базу).
Требуется вывести список заказов, которые были изменены в течении последних суток, но чтобы табличка в форме по понедельникам не была пустой решили в случае отсутствия корректировок выводить последние 10 изменённых заказов. То есть изначально непонятно, сколько строк выбирать из таблицы, чтобы произвести группировку.
Если подскажешь какое условие поставить чтобы группировать только часть информации из таблицы (понятно, что большинство заказов давно не используются и вытаскивать их при группировке каждый раз смысла нет)

P.S. Кстати, значения "одни сутки" и "минимум 10 заказов" могут меняться, в процедуре, в которой находится данный запрос они заданы как входные параметры, потому на цифрах sysdate-1 и rownum<=10 можно не зацикливаться, ставить любые значения

звиняюсь ошибочку сделал
WHERE (r_k > 10 and s_field >= (SYSDATE - 1 )) or (r_k<=10 and rownum<=10)
order by 1
странно что никто не поправил


на счет понедельника
имхо если понедельник то брать с "пятницы"

в идеале брать предыдущую дату "рабочий день" с календаря

сразу учтете 1,2 мая и тд

.....
stax
...
Рейтинг: 0 / 0
25.11.2016, 06:23
    #39354240
Mr.Fontaine
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
stax.., вот чтоб с календарями не возиться и решили выводить минимум 10 записей, не обращая в какой день они были загружены.
...
Рейтинг: 0 / 0
25.11.2016, 17:37
    #39354752
stax..
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
получение последних записей из таблицы
Mr.Fontainestax.., вот чтоб с календарями не возиться и решили выводить минимум 10 записей, не обращая в какой день они были загружены.
рано или поздно календарь придется вводить

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


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