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
randomizar com resultados do select
consulta aleatoria
Resultado de um select em ordem aleatória
Acesso Randômico
Query com Pesquisa Randomica é possivel ??


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: Bing [Bot] e 1 visitante