powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / получение последних записей из таблицы
18 сообщений из 18, страница 1 из 1
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #39352819
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
т.е. вся задача - просто вывести последние N записей из запроса?
...
Рейтинг: 0 / 0
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #39352876
Фотография Fogel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GlaysMr.Fontaine,
например так
Код: plsql
1.
2.
3.
...
    RANK ()
...


лучше DENSE_RANK
...
Рейтинг: 0 / 0
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #39353060
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stax..FogelОн троллирует таких, как ты.
...
Рейтинг: 0 / 0
получение последних записей из таблицы
    #39353084
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elicstax..пропущено...
Он троллирует таких, как ты.
не понял
я ж старался

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

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

Относительно группировки по всему объёму - сразу подумал, что это не комильфо, собственно поэтому своего решения и не написал (хотя и заглянул сюда в кои-то веки), т.к. отбор первых n строк подразумевает сортировку, а сортировка - выборку полного набора, то есть в данном случае группировку по всей массе, поэтому в лоб решать, применяя вначале агрегат, потому сортировку - это канонично, но на больших объёмах тяжело.
поэтому я бы действовал точно не в лоб: кода больше, но на громадных объёмах быстрее. есть мысль насчёт алгоритма, надо его только выразить...
...
Рейтинг: 0 / 0
получение последних записей из таблицы
    #39353331
Фотография Fogel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PS: относительно троллинга, насколько помню, фраза относилась к снобам, которые "набор знаний" считают заменой ума.
то есть тех, кто встречает по "одёжке" в виде этих самых знаний и тычет в RTFM каждому встречному.
просто не люблю снобов, тем более не очень умных, хотя и весьма образованных.
...
Рейтинг: 0 / 0
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #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
получение последних записей из таблицы
    #39354240
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
stax.., вот чтоб с календарями не возиться и решили выводить минимум 10 записей, не обращая в какой день они были загружены.
...
Рейтинг: 0 / 0
получение последних записей из таблицы
    #39354752
stax..
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Mr.Fontainestax.., вот чтоб с календарями не возиться и решили выводить минимум 10 записей, не обращая в какой день они были загружены.
рано или поздно календарь придется вводить

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


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