2017-03-14 5 views
2

Ich muss eine Zeichenfolge der Nummern 1-3 mit den Zahlen in zufälliger Reihenfolge für jede aus einer Tabelle ausgewählte Zeile generieren.Generieren einer Zeichenfolge in zufälliger Reihenfolge

Ich habe Folgendes versucht, bin aber nicht in der Lage, die Zufallszahlen für jede Zeile zu ändern (sie sind über alle Zeilen hinweg gleich).

SELECT name 
, (SELECT LISTAGG(COLUMN_VALUE) WITHIN GROUP (ORDER BY dbms_random.value) 
    FROM TABLE(SYS.ODCIVARCHAR2LIST('1', '2', '3')) 
    ) AS q_order 
FROM tableA 

Gewünschtes Ergebnis:

NAME  Q_ORDER 
------------------- 
Name1  123 
Name2  312 
Name3  213 

Was ich tatsächlich bekommen:

NAME  Q_ORDER 
------------------- 
Name1  312 
Name2  312 
Name3  312 

Version: Oracle 11.2.0

+0

Müssen sie alle Permutationen von {1, 2, 3} sein? Das ist nicht völlig zufällig; wirklich zufällig sollte auch 233, 131 und sogar 222 und 333 erlauben. – mathguy

+0

Und, wenn Sie wissen wollen, warum Ihr Versuch fehlschlug: Sie haben alle Zufälligkeit in einer Unterabfrage isoliert, die mit der äußeren Abfrage unkorreliert ist. Daher wird die Unterabfrage nur einmal berechnet, und derselbe Wert wird für jede Zeile in der äußeren Abfrage verwendet. Sie können erzwingen, dass die Unterabfrage korreliert wird, aber Sie erhalten eine sehr ineffiziente Implementierung Ihrer Anforderung. – mathguy

Antwort

0

So etwas ... (einfach, aber effizient) . Die zweite Spalte ist eine Zeichenfolge. Wenn Sie es als Nummer benötigen, wenden Sie TO_NUMER() darauf an. Natürlich werden die Werte in der zweiten Spalte jedes Mal, wenn Sie die Abfrage unterschiedlich sein (die Werte sind in der Tat zufällig!)

with 
    tablea (name) as (
     select 'Name1' from dual union all 
     select 'Name2' from dual union all 
     select 'Name3' from dual 
    ) 
select name, 
     case floor(dbms_random.value(0, 6)) 
      when 0 then '123' 
      when 1 then '132' 
      when 2 then '213' 
      when 3 then '231' 
      when 4 then '312' 
      else  '321' end as q_order 
from tablea 
; 

NAME Q_ORDER 
----- ------- 
Name1 123 
Name2 312 
Name3 213 
0

Ihr Ansatz wahrscheinlich mit einigen Optimierungen arbeiten. Oracle scheint die Tatsache zu optimieren, dass der Code für jede Zeile ausgeführt werden sollte.

Eine Methode besteht darin, eine äußere Referenz einzubeziehen, um diese Optimierung zu umgehen. Ich denke das ist ausreichend:

SELECT name, 
     (SELECT LISTAGG(COLUMN_VALUE) WITHIN GROUP (ORDER BY dbms_random.value) 
     FROM TABLE(SYS.ODCIVARCHAR2LIST('1', '2', '3')) 
     WHERE a.name is not null 
     ) AS q_order 
FROM tableA a; 
+0

Warum sollte der Code für jede Zeile ausgeführt werden? Ich habe bereits in einem Kommentar (in dem ich genau die Lösung angeboten habe, die du in eine Antwort geschrieben hast) erklärt, warum das ** nicht ** der Fall ist. Warum sollte für jede Zeile eine NICHT korrelierte Unterabfrage berechnet werden? – mathguy

Verwandte Themen