2013-07-16 9 views
10

Che cos'è un modo veloce/leggibile per SELEZIONARE una relazione da "nothing" che contiene un elenco di numeri. Voglio definire quali numeri impostando un valore iniziale e finale. Sto usando Postgres SQL e SQLite e sarei interessato alle soluzioni generiche che funzioneranno su entrambe le piattaforme/molte.SQL: selezionare un elenco di numeri da "nothing"

relazione uscita desiderata:

# x 
    0 
    1 
    2 
    3 
    4 

So che posso selezionare una singola riga dal "nulla": SELECT 0,1,2,3,4 Ma questo seleziona i valori come colonne invece delle righe e richiede per specificare tutti i valori nella query invece di utilizzare solo i miei valori iniziali e finali: 0 e 4.

In Postgres si hanno una funzione speciale generate_series per questo caso:

SELECT * FROM generate_series(0,4) x; 

Questo funziona bene, ma è non-standard. Posso anche immaginare alcune soluzioni complicate utilizzando tabelle temporanee, ma mi piacerebbe avere qualcosa di generico e semplice come:

SELECT * FROM [0..4] 

Forse utilizzando l'istruzione SEQUENCE o una combinazione di magia e SELECT 0SELECT 4?

+1

Si potrebbe anche usare numeri fino a 1.000 direi - metti forse un indice sul tavolo. Altrimenti, crea viste come numbers_to_1000, numbers_to_1000000 per incapsulare le giunzioni incrociate. –

+0

@ Juve, potresti accettare qualche risposta o postare la tua risposta e accettarla? –

+0

Quando ho iniziato a guardare, sono rimasto stupito da quanto sia imbarazzante questo compito apparentemente semplice. Ecco un articolo con alcune possibilità in più (ma suggerisce che nulla supera GENERATE_SERIES() da PostgreSQL): https://blog.jooq.org/2013/11/19/how-to-create-a-range-from-1 -to-10-in-sql/ – Dodecaphone

risposta

2

Grazie per tutte le risposte! A seguito della discussione mi sono reso conto che l'utilizzo di un numbers table non è troppo complicato e funziona bene e veloce su entrambe le molte piattaforme /:

CREATE TABLE integers (i integer); 
INSERT INTO integers (i) VALUES (0); 
INSERT INTO integers (i) VALUES (1); 
... 
INSERT INTO integers (i) VALUES (9); 
SELECT (hundreds.i * 100) + (tens.i * 10) + units.i AS x 
FROM integers AS units 
    CROSS JOIN integers AS tens 
    CROSS JOIN integers AS hundreds 

basta creare questa tabella una sola volta e può essere utilizzato ogni volta che è necessario un intervallo di numeri.

4

Bene in SQL Server (e PostgreSQL) userei ricorsiva di tabella comune: SQL Server, PostgreSQL

with recursive Numbers as (
    select 0 as Number 
    union all 
    select Number + 1 
    from Numbers 
    where Number < 4 
) 
select Number 
from Numbers 

SQL FIDDLE EXAMPLE

Ma, per quanto ne so, non c'è CON in SQLite.

Quindi, le soluzioni possibili potrebbe essere

  • creare una funzione definita dall'utente (this potrebbe essere utile)
  • creare una tabella con i numeri da 0 a numero massimo di cui avrete bisogno, e poi basta selezionare da questo modo:

    select Number from Numbers where Number >= 0 and Number <= 4 
    
+0

Il CTE ricorsivo funzionerebbe anche in Postgres (in effetti è l'unico modo "standard" per farlo - poiché quasi tutti i moderni DBMS supportano CTE ricorsivi oggigiorno) –

+0

true, ho appena provato ad aiutare con SQLite, perché sa come farlo in PostgreSQL, ma grazie, modifico la risposta –

+1

Mentre un CTE ricorsivo funzionerebbe nella maggior parte dei moderni DBMS, è stato dimostrato come [un modo molto inefficiente di generare una sequenza] (http: // www .sqlperformance.com/2013/01/T-SQL-query/generate-un-set-2). Penso che la tabella dei numeri sia di gran lunga l'approccio migliore. – GarethD

4

Un modo semplice per fare questo in PostgreSQL e SQLite è la seguente:

sqlite> select 1 union select 2 union select 3; 
1 
2 
3 

Dovrebbe funzionare nella maggior parte dei sistemi RDBMS, ma IIRC in Oracle si dovrebbe usare:

select 1 from dual union select 2 from dual union select 3 from dual; 

Ma non ho un DB Oracle per testarlo su.

0

qualche altra alternativa (provato in postgres, ma dovrebbe lavorare con altri)

select (0) as count union values (1),(2),(3),(4),(5)

estendere questa sql con il codice sarà semplice.

Problemi correlati