27.10.2015

PL/SQL: MODEL (пример)

У движка отчетов JasperReports есть особенность: область детализации строго горизонтальна и занимает всю ширину страницы. Если нужно напечатать несколько маленьких бланков, которые умещаются по 2 штуки в ряд, то придется печатать всё-таки по одному.

Выход - подать на вход выборку, уже разбитую на 2 колонки.

Для простейших случаев наподобие представленного можно использовать MODEL - мощную инструкцию PL/SQL, позволяющую с выборкой производить операции с нетривиальной логикой. Применяется крайне редко в особо тяжелых случаях.
select * from (select id1, name1, lead(id2, 1) over(order by null) id2, lead(name2, 1) over(order by null) name2 from (select id1, name1, id2, name2 from (select 1 r, 10 id, 'a' name from dual union select 2 r, 15 id, 'b' name from dual union select 3 r, 20 id, 'c' name from dual union select 4 r, 25 id, 'd' name from dual union select 5 r, 30 id, 'e' name from dual) model dimension by(r, id, name) measures(0 id1, cast(null as varchar2(255)) name1, 0 id2, cast(null as varchar2(255)) name2) rules(id1 [ mod(r, 2) != 0, id, name ] = cv(id), id2 [ mod(r, 2) = 0, id, name ] = cv(id), name1 [ mod(r, 2) != 0, id, name ] = cv(name), name2 [ mod(r, 2) = 0, id, name ] = cv(name)))) where id1 != 0
В приведенном примере сначала мы разбиваем выборку по колонкам в зависимости от четности/нечетности порядкового номера, затем на уровне выше с помощью функции LEAD склеиваем строки, чтобы убрать шахматный порядок в данных. Наконец, ограничением where id1 != 0 отсекаем пустые строки, образовавшиеся после склейки.





23.10.2015

PL/SQL: Месяцы в родительном падеже

Не хотелось плодить кучу условий и использовать какие-либо кириллические константы, поэтому вот:
  function month_rodp(p_date in date) return varchar2
  is
           mon varchar2(20);
  begin
     mon := trim(lower(to_char(p_date, 'MONTH')));
     if (to_char(p_date, 'MM')) in (3,8) then
        mon := mon || chr(1072 using NCHAR_CS);
     else
        mon := substr(mon, 1,  length(mon)-1) || chr(1103 using NCHAR_CS);
     end if;
     return mon;
  end month_rodp;