Treinamentos Oracle - Nerv Informática

Arrays em PLSQL


Veja também:
Preenchimento automático de registros num banco de dados
Select com ordem aleatória


Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
  

Mensagempor lopes_andre em Seg, 24 Nov 2008 2:43 pm

Viva,

Estou a fazer um programa em PLSQL que irá fazer um sorteio. Este sorteio além de ser random tem também uma ponderação.

Estou-me a basear neste programa em excel: http://www.dailydoseofexcel.com/archive ... dom-sorts/

Eu queria saber qual será a melhor maneira de lidar com a seguinte situação:

No meu caso, atribui ponderações as categorias da empresa. O empregado irá ter um valor de ponderação igual ao da sua categoria.

Se a ponderação da categoria do empregado XPTO tiver o valor 6 eu teria de criar um array com 6 valores, cada um desses valores seria gerado segundo a formula -->

Código: Selecionar todos
=(RAND()^LOG(1-1/(6+1); 0,5))*1000


esta formula é ainda uma formula em excel. Desses 6 valores gerados pela formula no array eu iria escolher o mais alto.

Isto será possivel de fazer em PLSQL ou terei de tomar outro caminho?


Desde já obrigado.

Cumprimentos,
André.
lopes_andre
Localização: Lisboa

Mensagempor dr_gori em Seg, 24 Nov 2008 3:12 pm

Acho que não tem problema.
Pra fazer número randômicos, pode-se usar DBMS_RAND.
http://glufke.net/oracle/viewtopic.php?p=7496
http://glufke.net/oracle/viewtopic.php?t=243

Código: Selecionar todos
SQL> select dbms_random.random from dual;

    RANDOM
----------
-1.262E+09

SQL> /

    RANDOM
----------
619010116

SQL> /

    RANDOM
----------
406715840

SQL> /

    RANDOM
----------
-615930667

SQL> 



Pra fazer LOG, também não é problema:
http://www.techonthenet.com/oracle/functions/log.php
Código: Selecionar todos
SQL> select log(10, 100) from dual;

LOG(10,100)
-----------
          2

SQL>


Agora, é só montar algo que busque esses resultados e pegue o maior deles...
dr_gori
Localização: Porto Alegre - RS

Thomas F. G
Twitter: @plsql

Mensagempor Trevisolli em Seg, 24 Nov 2008 3:49 pm

Show de bola, Dr_Gori.

Só complementando, para se pegar o maior valor, pode ainda usar o GREATEST (Se não me engano 9i e superiores):
Código: Selecionar todos
SELECT GREATEST (2, 5, 12, 3) maior_valor
  FROM DUAL;

Retorna: 12.

Qualquer coisa, tamos aí.
Trevisolli
Localização: Araraquara - SP

Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Mensagempor dr_gori em Seg, 24 Nov 2008 4:02 pm

Mandou bem!

Mas eu acho que talvez ele vai ter que usar outra forma de pegar o maior. Talvez inserir numa global temporary table (caso não seja fixo o número máximo da "ponderação" dele...

Isso porque é impossível fazer GREATEST de um array.
Exemplo:
Código: Selecionar todos
SQL> declare
  2   TYPE ARRAY IS TABLE OF number INDEX BY BINARY_INTEGER;
  3   
  4   t ARRAY;
  5   
  6  begin
  7 
  8    t(1) :=10;
  9    t(2) :=20;
10    t(3) :=30;
11   
12    dbms_output.put_line ( greatest(t) );
13 
14 
15  end;
16  /
  dbms_output.put_line ( greatest(t) );
                         *
ERROR at line 12:
ORA-06550: line 12, column 26:
PLS-00306: wrong number or types of arguments in call to 'GREATEST'
ORA-06550: line 12, column 3:
PL/SQL: Statement ignored


SQL> 


Acho que é melhor inserir os valores numa GTT e fazer MAX simplesmente.
dr_gori
Localização: Porto Alegre - RS

Thomas F. G
Twitter: @plsql

Mensagempor lopes_andre em Ter, 25 Nov 2008 8:14 am

Viva,

Desde já muito obrigado pela ajuda!

Já estou a construir o programa, no entanto estou com dificuldade com o DBMS_RANDOM. Não vou trabalhar com arrays, vou antes enviar os valores gerados para uma tabela temporaria, vai simplificar bastante as coisas... agora o entrave..

No excel estou usando esta formula:

Código: Selecionar todos
=RAND()^LOG(1-1/(N+1);0,5)


Quanto mais aproximo o N de 10 que será o peso/ponderação máxima mais provavel será serem gerados valores proximos de 1.

Fazer random de um LOG no excel funciona bem. No oracle não estou a conseguir fazer random de um LOG. Será que tem jeito de fazer random de um LOG?


Desde já obrigado.

Melhores cumprimentos
André.
lopes_andre
Localização: Lisboa

Mensagempor ricardorauber em Qua, 26 Nov 2008 9:55 am

Daria para fazer assim também:

Código: Selecionar todos
DECLARE

  TYPE nums IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
  vetor nums;
 
  FUNCTION maior RETURN NUMBER IS
    cont NUMBER := 0;
  BEGIN
    FOR i IN vetor.FIRST .. vetor.LAST LOOP
      IF vetor(i) > cont THEN
        cont := vetor(i);
      END IF;
    END LOOP;
    RETURN cont;
  END maior;
 
BEGIN

  vetor(1) := 3;
  vetor(2) := 5;
  vetor(3) := 4;
 
  dbms_output.put_line(maior);
 
END;
ricardorauber
Localização: Canoas RS

Mensagempor ricardorauber em Qua, 26 Nov 2008 10:12 am

Para calcular exponencial, random e log

Código: Selecionar todos
DECLARE

  TYPE nums IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
  vetor nums;
 
BEGIN

  -- LOG(1-1/(1+A1);0,5)

  -- Insere valores
  FOR i IN 1 .. 10 LOOP
    vetor(i) := i;
    dbms_output.put_line(vetor(i));
  END LOOP;
 
  -- Separador
  dbms_output.put_line(rpad('-',100,'-'));
 
  -- Adiciona o log
  FOR i IN vetor.FIRST .. vetor.LAST LOOP
    vetor(i) := LOG(0.5,1-1/(1+vetor(i)));
    dbms_output.put_line(vetor(i));
  END LOOP;
 
  -- Separador
  dbms_output.put_line(rpad('-',100,'-'));
 
  -- Adiciona o random e calcula a potencia (exponencial)
  FOR i IN vetor.FIRST .. vetor.LAST LOOP
    vetor(i) := power(trunc(dbms_random.value(1,10)), vetor(i));
    dbms_output.put_line(vetor(i));
  END LOOP;
 
END;


Saída:

Código: Selecionar todos
1
2
3
4
5
6
7
8
9
10
----------------------------------------------------------------------------------------------------
1
,5849625007211561814537389439478165087624
,41503749927884381854626105605218349124
,3219280948873623478703194294893901758618
,2630344058337938335834195144584263329081
,22239242133644792598823037328401429991
,1926450779423958925580306827681691913527
,1699250014423123629074778878956330175169
,1520030934450499849628415415937571583599
,1375035237499349083290436172364027828474
----------------------------------------------------------------------------------------------------
2
1,90150749823037254511681818840789155874
1,77777777777777777777777777777777777777
2,02860491380619980243290499234874746619
1,78237306890983628007321950484593599572
1,1666666666666666666666666666666666667
1,45480229597148250562035976049055480278
1,45261210788256229152408722218618633821
1,37174211248285322359396433470507544584
1,09999999999999999999999999999999999999
ricardorauber
Localização: Canoas RS


Voltar para PL/SQL

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 2 visitantes