2016-03-02 12 views
9

Se faccioCosa utilizza LISTAGG con ORDER BY NULL come criterio dell'ordine?

SELECT LISTAGG(COLUMN_VALUE) WITHIN GROUP (ORDER BY NULL) AS OrderByNULL, 
     LISTAGG(COLUMN_VALUE) WITHIN GROUP (ORDER BY 1)  AS OrderByCONST, 
     LISTAGG(COLUMN_VALUE) WITHIN GROUP (ORDER BY ROWNUM) AS OrderByROWNUM 
FROM TABLE(SYS.ODCIVARCHAR2LIST('5', '222', '4')); 

Il risultato è:

ORDERBYNULL ORDERBYCONST ORDERBYROWNUM 
----------- ------------ ------------- 
222,4,5  222,4,5  5,222,4 

La query sembra aver fatto un ordinamento alfanumerico utilizzando ORDER BY con ordine non deterministico (NULL o una costante) e ha mantenuto la ordine di input quando si utilizza ORDER BY ROWNUM (deterministico).

La documentazione LISTAGG afferma che:

L'order_by_clause determina l'ordine in cui vengono restituiti i valori concatenati. La funzione è deterministica solo se l'elenco di colonne ORDER BY ha ottenuto un ordinamento univoco.

E quando guardando analytic functions si afferma che:

Ogni volta che i risultati order_by_clause nei valori identici per più righe, la funzione si comporta come segue: [...] Per tutte le altre funzioni analitiche, la il risultato dipende dalle specifiche della finestra. Se si specifica una finestra logica con la parola chiave RANGE, la funzione restituisce lo stesso risultato per ciascuna delle righe. Se si specifica una finestra fisica con la parola chiave ROWS, il risultato non è deterministico.

Quindi, per quanto posso dire dalla documentazione un ordinamento non-deterministico è prevedibile - tuttavia, la funzione fornisce un'uscita deterministico sulla base di una sorta di testo e non l'ordine in cui vengono elaborate le righe (che è lo commonly held view).

Questo è diverso al comportamento di altre funzioni analitiche (quando si utilizza una finestra fisico con la parola chiave ROWS):

SELECT LAST_VALUE(COLUMN_VALUE) 
     OVER (ORDER BY NULL ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
     AS BYNULL, 
     LAST_VALUE(COLUMN_VALUE) 
     OVER (ORDER BY 1  ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
     AS BYCONST, 
     LAST_VALUE(COLUMN_VALUE) 
     OVER (ORDER BY ROWNUM ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
     AS BYROWNUM 
FROM TABLE(SYS.ODCIVARCHAR2LIST('5', '222', '4')); 

che dà un risultato coerente per tutti i diversi ordinamenti:

BYNULL BYCONST BYROWNUM 
------ ------- -------- 
4  4  4 
4  4  4 
4  4  4 

Esiste documentazione ufficiale su come viene applicato un ordine quando a LISTAGG viene fornito un ordinamento non deterministico?

Nota: Il comportamento di ORDER BY NULL è commentato here affermando:

In questo esempio, gli elementi sono stati aggregati alfabetico, nonostante la clausola NULL ordinazione. Questo sembra essere il comportamento predefinito quando si utilizza un'espressione ORDER BY costante

Ma questo è solo un commento sul comportamento in un sito non Oracle.

+4

Un insieme di risultati fornisce una prova praticamente nulla del determinismo. Se si utilizza una costante o 'NULL', quindi si aspettano i risultati in qualsiasi ordine. La documentazione è abbastanza chiara che non è possibile fare affidamento sull'ordinazione quando le chiavi 'order by' hanno gli stessi valori. –

+0

Tuttavia, se si ripete il test (con dati diversi) si otterrà sempre lo stesso ordine alfanumerico. Di quanti set di risultati hai bisogno per questo ordine di essere considerato un elemento di design piuttosto che una coincidenza? – MT0

+2

Qualunque cosa stia facendo sembra ignorare NLS_COMP/SORT. Presumibilmente è un dettaglio di implementazione. piuttosto che una caratteristica di design - e quindi non sembra essere documentato, anche su MOS. E come tale, non è qualcosa su cui puoi fare affidamento - dal momento che potrebbe cambiare in una versione futura? È interessante, ma non è sicuro se sia utile. –

risposta

0

Probabilmente l'ordine dipenderà da molti fattori, tra cui il piano di esecuzione della query, la configurazione dell'istanza, la versione del database, se si è su exadata o meno.

Se non si fornisce a Oracle alcun criterio specifico per ordinare i dati, non è possibile fare affidamento su alcun ordine specifico, anche se dalle prove si ottiene che i dati vengano ordinati in modo coerente in un modo specifico.

Secondo Oracle documentation for listagg:

  • L'order_by_clause determina l'ordine in cui vengono resi i valori concatenati. La funzione è deterministica solo se l'elenco di colonne ORDER BY ha ottenuto un ordinamento univoco.