Задать вопрос
Ответы пользователя по тегу Oracle
  • Почему вложеность запроса так сильно меняет скорость?

    @alexalexes
    1. Отсутствие индексов на всех выводимых, группируемых, участвующих в условиях выборки полях.
    2. t_report_detail не таблица, а вью. Не каждая вью адекватно приготовлена, чтобы над ней можно было легко делать еще какую-либо агрегацию. Пишите другую вью на основе ее текста запроса или изменяйте принцип получения агрегированных данных, чтобы не было узских мест.
    PS: explain analyze - это ваши очки. Администратор СУБД слеп без него.
    PPS: Если работаете в Toad, то простой запуск запроса в редакторе не всегда адекватен при измерении времени. Так как он получает только первые 500 записей. Поэтому, если запрос усложнить, то план выполнения может резко поменяться с учетом получения 500 записей на конечном этапе.
    Ответ написан
    Комментировать
  • Как пронумировать строки в группе?

    @alexalexes
    Партиции тут не требуются, все зависит только от характера сортировки:
    select t.a, t.b, t.c,
           dense_rank() over(order by t.a, t.b, t.c) rnk_dense
     from t_table t

    PS: Нужно больше примеров, когда изменяются a, b и c в пределах одной выборки, тогда можно точнее написать сортировку.
    Ответ написан
    Комментировать
  • Существуют ли что-то, что не поддается миграции с Oracle на PostgreSQL?

    @alexalexes
    Может поздние версии (после 10-й) Оракла и легко переносить на PostgreSQL, то ранние версии вам доставят особое удовольствие.
    Тут вам нестандартный синтаксис CTE для иерархических запросов, также нестандартный синтаксис для джоинов с плюсиками. Столкнетесь с особенностями работы с бинарными полями CLOB/BLOB, где-то придется переписывать шаманства с преобразованием дат. Где-то придется убрать костыли для оптимизации конкретных запросов (или для компенсации бага в выборки данных, бывают у Оракла некоторые приколы с distinct или группировками), или переписать их полностью.
    Одним автоматическим переносом не отделаетесь, придется отлаживать и тестировать каждый перенесенный элемент, чтобы он не только не падал в ошибку, но не был узким местом в производительности.
    Ответ написан
    Комментировать
  • Как составить SQL запрос с разбиением дат на несколько?

    @alexalexes
    -- Тестовая выборка
    with t as (select to_date('2024-09-17 11:52:17', 'yyyy-mm-dd hh24:mi:ss') begin_date, to_date('2024-12-17 11:52:17', 'yyyy-mm-dd hh24:mi:ss') end_date, 3 Cnt from dual union
    select to_date('2024-06-10 14:52:19', 'yyyy-mm-dd hh24:mi:ss') begin_date, to_date('2024-07-10 14:52:19', 'yyyy-mm-dd hh24:mi:ss') end_date, 1 Cnt from dual)
    -- Иерархический запрос
    select distinct T.*,
           add_Months(T.Begin_Date, Level - 1) as Current_Date, -- отсчет месяцев
           Level as Current_Val  -- текущее значение отсчета
      from T
      CONNECT BY add_Months(T.Begin_Date, Level) <= T.End_Date
    order siblings by T.Begin_Date desc
    Ответ написан
    Комментировать
  • Как вывести день,час, минуты?

    @alexalexes
    Если одну дату вычесть из другой даты, то получите количество дней в виде вещественного числа.
    Добавив немного математики вычисления остатков, получите все компоненты разницы дат:
    select trunc(sysdate - to_date('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS')) days,
       mod(trunc((sysdate - to_date('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS')) * 24), 24)  hours,
       mod(trunc((sysdate - to_date('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS')) * 24 * 60), 60) minutes,
       mod(trunc((sysdate - to_date('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS')) * 24 * 60 * 60), 60) seconds
    from dual

    Вариант 2:
    select extract(day from (sysdate - to_timestamp('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS'))) days,
           extract(hour from (sysdate - to_timestamp('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS'))) hours,
           extract(minute from (sysdate - to_timestamp('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS'))) minutes,
           extract(second from (sysdate - to_timestamp('03.10.2004 17:03:28', 'DD.MM.YYYY HH24:MI:SS'))) seconds
    from dual
    Ответ написан
    4 комментария
  • Возможно ли в oracle sql объединить JSON массивы, являющиеся записями запроса?

    @alexalexes
    Смотрите в сторону функции ListAgg - она объединит все значения через разделитель.
    Потом останется только обрамить результат в скобки:
    select '[' || ListAgg(item, ',') over (order by rownum) || ']'  as item_arr
      from table

    PS: ListAgg работает с данными, которые можно привести к varchar/varchar2. То есть, у вас есть физическое ограничение в 4000 символов в результирующей строке. Или у вас данные изначально в BLOB/CLOB.
    В этих случаях вам нужно использовать хранимую функцию, поскольку в чистом SQL вы не сможете работать с безразмерными атрибутами.
    PPS: А вообще, нужно избавиться от JSON и нормализовать таблицу.
    PPPS: Если вы делаете API, то формировать JSON для ответа API - это не функция СУБД, этим должна заниматься прослойка перед СУБД.
    Ответ написан
    Комментировать
  • Как из полученного массива получить данные?

    @alexalexes
    Если вам понадобилось лезть внутрь JSON средствами SQL, значит в этом месте у вас архитектурный промах.
    Нужно провести нормализацию данных этого поля, раскидав значения этих свойств еще как минимум в 2 таблички при помощи среды, которая может обращаться к Oracle и парсить JSON (если у вас не 12c Oracle).
    Ответ написан
    Комментировать
  • Откуда скачать Oracle Client 12.2?

    @alexalexes
    Только гуглить по названию оригинального файла и натыкаться на непонятные ftp-файлопомойки:
    200.2.13.127/software/oracle/client
    Тут 12.1 версия, но, наверное, не суть важно.
    Ответ написан
    Комментировать
  • Как получить timestamp,обрезав пустое время?

    @alexalexes
    komino, это проблема разработчика, а не конфига драйвера СУБД, как он будет интерпретировать значение даты в конкретном запросе, если ему не подходит статичный шаблон nls_date_format. Такой шаблон не имеет в себе лексического интерпретатора, способного выполнять условные операторы.
    Решение:
    select
    -- вариант 1
    to_char(sysdate, 'DD.MM.YYYY' || decode(sysdate - trunc(sysdate), 0, '', ' HH24:MI:SS')) as your_format_date_1, 
    -- вариант 2
    case
      when sysdate - trunc(sysdate) > 0
      then to_char(sysdate, 'DD.MM.YYYY HH24:MI:SS')
      else to_char(sysdate, 'DD.MM.YYYY')
    end as your_format_date_2
    from dual;
    Ответ написан
  • Как НЕ фиксировать транзакцию после отработки php скрипта?

    @alexalexes
    $_POST['SQL'];
    Ой, вы доверяете клиенту настолько, что позволяете ему самому формировать текст запроса для бэкенда?
    У такой модели взаимодействия уровень безопасности еще ниже, чем у подготовленных запросов со строковой склейкой параметров.
    Идеология выполнения скриптов в PHP такая, чтобы выполнить все атомарные действия, зафиксировать результат (или откатиться), отдать ответ и умереть.
    Есть какие-то примеры данного "фокуса"?

    Есть. Технология называется web sockets, она представляет другую идеологию - называется длинные запросы. Когда клиент открывает соединение с сервером и ждет от сервера сообщений (или сам их отправляет в соккет), при этом скрипт сервера в бесконечном цикле опрашивает открытый соккет. Не завершая скрипт, на сервере можно либо ожидать появление сообщения в соккете, либо выполнять что-то по транзакции, если имеется принятое сообщение.
    Проблема еще в том, что PHP не сильно приспособлен для этого режима. Вам придется делать бесконечную петлю обработки в скрипте:
    while(true)
    {
      // исполняемый код для всех клиентов соккетов
    }

    И вам нужно самим делать механизм сессий, чтобы отличать одного клиента от другого, поскольку запущенный скрипт будет принимать сообщения от всех клиентов.
    Для этих целей больше годится NodeJS. Там все соккеты разбиты по обработчикам событий, можно выделить контекст одного конкретного клиента.
    Резюмируя, могу сказать.
    а) Вы пишите свой продвинутый редактор запросов (а-ля PHPMyAdmin но с поддержкой транзакций) и у вас неправильно выбран вид сервера для бэкенда (PHP вместо NodeJS). Технические требования для взаимодействия клиента и сервера не имеют подходящей реализации технологии на сервере (web sockets).
    б) Либо у вас приложение не предполагает работы, связанной с редактированием запросов пользователем. Вы просто переносите опыт разработки desktop приложений на веб разработку.
    В этом случае вы не правильно делаете то, что формируете запросы на клиенте. Толстую бизнес-логику, предполагающую взаимодействие с базой данных с фиксацией или не фиксацией транзакции нужно переносить на бэкенд, либо в хранимые процедуры и функции СУБД.
    Ответ написан
    2 комментария
  • Как сравнить по времени в таблицах, отбросив минуты и секунды до часов?

    @alexalexes
    Select t1.ID, t1.TIME
    from 
    TABLE_1 t1 
    JOIN TABLE_2 t2 ON t1.ID=t2.ID
                  and to_char(t1.TIME, 'DD.MM.YYYY HH24') = to_char(t2.TIME, 'DD.MM.YYYY HH24')

    Вариант 2 (возможно, пригодится при оптимизации, так как на выходе сравниваются значения в типе дата время, а не строк):
    ... and trunc(t1.TIME, 'hh24') = trunc(t2.TIME, 'hh24')

    PS: Хорошо бы еще индекс создать под этот формат времени для колонок t1.TIME и t2.TIME, тогда запрос будет всегда производителен.
    Ответ написан
    4 комментария
  • Как создать паттерн для REGEXP_LIKE для двух значений?

    @alexalexes
    Если в СУБД вы видите функции для работы с регулярными выражениями, то это еще не значит, что реализована вся их мощь.
    Например, для вашего случая, чтобы реализовать AND, нужно, чтобы исполнитель регулярок мог обрабатывать ретроспективные или опережающие проверки.
    За функциями Oracle такого функционала не замечено, в силу того, что эта СУБД не для полнотекстового поиска, а инструмент для быстрой работы с хорошо структурированными данными.
    Ковыряние в фрагментах текста - не конек реляционных СУБД, таким системам индексируемые данные подавай.
    Поэтому функционал регулярных функций ограничен, реализованы чуть лучше чем like.
    Ответ написан
    Комментировать
  • Как в Oracle или Teradata разбить все строки таблицы на N равновеликие СЛУЧАЙНЫЕ выборки?

    @alexalexes
    Практически методом Монте-Карло помечаем числами из случайного интервала записи таблицы и берем интересуемую порцию по этой случайной метрике. Поскольку, рандом у нас по равномерному закону распределения работает, то и порцию данных вы получите примерно ожидаемой длины.
    select *
    from (
    select t.*, dbms_random.value(0, 100) rnd
      from table t
    ) A
    where A.rnd <= 30 -- выбираем примерно 30% случайных записей от ген. выборки
    Ответ написан
  • Как правильно сделать группировку sql?

    @alexalexes
    Пронумеруйте Rank-ом или dense_rank c таким же partition с сортировкой rownum и отрежьте лишнее оберткой:
    select * from (...) where rnk = 1
    PS: Лучше обходиться без оконных функций, если есть решение более классическое. Окошки заставляют обходить выборку заново и ухудшают план выполнения запроса.
    Ответ написан
    1 комментарий
  • Как занести сразу несколько значении в таблицу?

    @alexalexes
    Самый топорный способ подготовки файла с данными.
    1. Открываете файл в Notepad++.
    2. Ctrl+H (Замена).
    3. Режим поиска ставите "Регулярные выражения".
    4. Найти:
    ^
    5. Заменить (название таблицы подставляете свое):
    insert into table\(name\) values \('
    6. Нажать "Заменить все".
    7. Найти:
    \r
    8. Заменить:
    '\);
    9. Нажать "Заменить все".
    В итоге получаете 500 строк инсертов. Выполняете их одной транзакцией любым доступным способом.
    Ответ написан
    Комментировать