quarta-feira, 7 de abril de 2010

Retorna registros randômicos entre um grupo de registros

Hi!

Abaixo segue um exemplo bem interessante onde dentro de um grupo de registros é escolhido um registro aleatório.  Note que além da função DBMS_RANDOM, são utilizadas as funções RANK e OVER.
Em nossa tabela exemplo, teremos os seguintes dados:

Tabela: teste_random

Nome    Numero

======  ======
Felipe  1
Felipe  2
Felipe  3
Thiago  1
Thiago  2
Thiago  3
Edna    1

Segue SCRIPT para a criação da tabela e INSERTs:

create table teste_random
( nome   char(6)
 ,numero char(1)
)
/
insert into teste_random
values
('Felipe','1')
/
insert into teste_random
values
('Felipe','2')
/
insert into teste_random
values
('Felipe','3')
/
insert into teste_random
values
('Thiago','1')
/
insert into teste_random
values
('Thiago','2')
/
insert into teste_random
values
('Thiago','3')
/   
insert into teste_random
values
('Edna','1')
/
COMMIT
/


Qual a idéia. Temos 3 registros para o nome “Felipe”, 3 para o nome “Thiago” e 1 registro para o nome “Edna”. Queremos que dentro de um determinado grupo de registros (grupos por nome) seja escolhido um registro aleatório. Exemplo, para o grupo “Felipe”, onde há três registros “Felipe, 1”, “Felipe, 2” e “Felipe, 3”, o programa deve escolher um destes três registros. E faça isso também para os grupos ”Thiago” e “Edna”. No caso do grupo referente ao nome “Edna”, só existe um registro, portanto, sempre vai retornar o mesmo. Quanto aos outros, para cada grupo, em cada execução ele deve trazer um registro aleatoriamente.

Segue o SELECT que fará isto:
select nome, numero
from (
      select nome, numero
            ,rank() over(partition by nome order by numero) rnk
      from   teste_random
     ) a
where  rnk = (select ceil(dbms_random.value(0,(select count(*) from teste_random te2 where te2.nome = a.nome))) from dual)
 


Segue algumas execuções:



Falows!

segunda-feira, 5 de abril de 2010

Parâmetros tipo Data e Numérico vindos do EBS

Opa!


Quando trabalhamos com datas e números, sempre temos que prestar a atenção como estes dados estão chegando ao programa. É comum acontecer os famosos erros de formato referentes a números ou datas inválidas, principalmente, quando estamos construindo um determinado programa onde temos que passar estes valores para outros programas através de parâmetros.  Um problema muito comum acontece quando estamos trabalhando com concorrentes no EBS passando parâmetros para programas armazenados no banco. Segue abaixo os passos para solucionar estes problemas:


1) O primeiro passo é, quando for definir os parâmetros de um programa concorrente, colocar como listas de valores, as nativas do Oracle, FND_NUMBER e FND_STANDARD_DATE para os tipos NUMBER e DATE, respectivamente.

2) No seu programa armazenado em banco, numa PROCEDURE, por exemplo, crie os parâmetros que receberão os dados, declarando-os com o tipo VARCHAR2.

3) Dentro do seu programa utilize as funções abaixo para a conversão:


Exemplo 1 (utilização no corpo do programa):
...
  wvl_item number;
  wdt_hoje date;
  --
begin
  -- No caso de conversão para números.
  wvl_item := fnd_number.canonical_to_number(pvl_item); -- pvl_item: parâmetro do tipo varchar2.
  --
  -- No caso de conversão para data.
  wdt_hoje := fnd_date.canonical_to_date(pdt_entrega); -- pdt_entrega: parâmetro do tipo VARCHAR2.
end;


Exemplo 2 (utilização na área de declaração de variáveis):
...
  wvl_item number default fnd_number.canonical_to_number(pvl_item);
  wdt_hoje date   :=      fnd_date.canonical_to_date(pdt_entrega);
  --
begin
  ...
  ...
  ...
end;


O contrário também pode ser feito com a mesma função. Converter um numérico ou data para string:
...
  wvl_item varchar2(38);
  wdt_hoje varchar2(20);
  --
begin
  -- No caso de conversão para caracter.
  wvl_item := fnd_number.number_to_canonical(vl_item);
  --
  -- No caso de conversão para caracter.
  wdt_hoje := fnd_date.date_to_canonical(sysdate);
end;


O segredo destas funções é que as mesmas são específicas para o EBS, logo elas “sabem”, digamos assim, qual o formato que a suíte está trabalhando. Se você quiser saber quais são estes formatos, uma dica é verificar no LOG do concorrente as informações a respeito dos parâmetros passados para o concorrente no momento da execução, lá ele mostra cada parâmetro com seu respectivo valor informado. Note que ele não passa os valores no formato que escolhemos na janela de parâmetros do concorrente e sim no formato que ele está trabalhando em background.


Forte abraço!