SQL SELECT per ottenere i primi N interi positivi

Ho bisogno di ottenere un set di risultati contenente i primi N interi positivi. È ansible utilizzare solo l’istruzione SQL SELECT standard per ottenerli (senza alcuna tabella di conteggio fornita)?

Se non è ansible, esiste un modo specifico MySQL per raggiungere questo objective?

Sembra che quello che vuoi sia un dummy rowset .

In MySQL , è imansible senza avere un tavolo.

La maggior parte dei sistemi principali fornisce un modo per farlo:

  • In Oracle :

     SELECT level FROM dual CONNECT BY level <= 10 
  • In SQL Server :

     WITH q AS ( SELECT 1 AS num UNION ALL SELECT num + 1 FROM q WHERE num < 10 ) SELECT * FROM q 
  • In PostgreSQL :

     SELECT num FROM generate_series(1, 10) num 

MySQL manca qualcosa del genere e questo è un grave inconveniente.

Ho scritto un semplice script per generare dati di test per le tabelle di esempio nei miei post del blog, forse sarà utile:

 CREATE TABLE filler ( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT ) ENGINE=Memory; CREATE PROCEDURE prc_filler(cnt INT) BEGIN DECLARE _cnt INT; SET _cnt = 1; WHILE _cnt <= cnt DO INSERT INTO filler SELECT _cnt; SET _cnt = _cnt + 1; END WHILE; END $$ 

Chiami la procedura e il tavolo viene riempito con i numeri.

Puoi riutilizzarlo durante la durata della sessione.

Una ansible soluzione (certamente non molto elegante) è quella di utilizzare qualsiasi tabella con un numero sufficientemente grande di record.

Per i primi 10 numeri interi (utilizzando mysql.help_relation, ma qualsiasi tabella dovrebbe fare), è ansible utilizzare la seguente query:

 SELECT @N := @N +1 AS integers FROM mysql.help_relation , (SELECT @N:=0) dum LIMIT 10; 

Questo potrebbe anche essere inserito in una funzione tenendo Min e Max.

Soluzione strana, ma …

 SELECT 1 UNION SELECT 2 UNION SELECT 3.... 

La sequenza che propongo consente al programmatore di eseguire la seguente query:

 select value from sequence where value>=15 and value<100; 

E per ottenere i risultati attesi: la sequenza di numeri interi tra 15 (inclusi) e 100 (esclusivi).

Se è quello che vuoi, dovrai creare le due viste seguenti, viste che dichiarerai una sola volta:

 create view digits as select 0 n union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9; create view sequence as select u.n+tn*10+hn*100 as value from digits as u cross join digits as t cross join digits as h; 

In questo modo hai la sequenza con un SELECT intuitivo ...

Spero che sia d'aiuto.

Supponendo che tu voglia recuperarli da una tabella, qui N è 10, assumendo che intcolumn sia la colonna con i numeri in essa contenuti.

 SELECT intcolumn FROM numbers WHERE intcolumn > 0 LIMIT 10 

Modifica : nel caso in cui stessimo cercando di ottenere il set matematico di numeri positivi senza un tavolo, vorrei riconsiderare, può essere intenso (a seconda dell’implementazione). Pratica comunemente accettata sembra essere quella di creare una tabella di ricerca piena di numeri, e quindi utilizzare la query precedente.

Questo può aiutare

Per ottenere un intero casuale R nell’intervallo i <= R

SELECT FLOOR(7 + (RAND() * 5));

Se sai che N è limitato (e di solito lo è), puoi usare una costruzione come:

 select (a.digit + (10 * b.digit) + (100 * c.digit) + (1000 * d.digit) + (10000 * e.digit) + (100000 * f.digit)) as n from (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as e cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as f; 

che genererà il primo milione di numeri. Se hai bisogno solo dei numeri positivi, aggiungi semplicemente + 1 all’espressione.

Si noti che in MySQL, in particolare, i risultati potrebbero non essere ordinati. Devi aggiungere l’ order by n alla fine se hai bisogno di numeri ordinati. Ciò aumenterà drammaticamente il tempo di esecuzione, tuttavia (sulla mia macchina, è salito da 5 ms a 500 ms).

Per domande semplici, ecco una query solo per i primi 10000 numeri:

 select (a.digit + (10 * b.digit) + (100 * c.digit) + (1000 * d.digit)) as n from (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c cross join (select 0 as digit union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as d; 

Questa risposta è adattata dalla seguente query che restituisce un intervallo di date: https://stackoverflow.com/a/2157776/2948

Sono abbastanza sicuro che non puoi farlo, se capisco correttamente la tua domanda.

Come ho capito la tua domanda, vuoi la lista, da una singola istruzione SQL, senza dover fare riferimento a una tabella specifica?

Sono abbastanza sicuro che non è ansible in alcun dialetto SQL. Se dovessi ottenere un numero incrementale in sequenza insieme ai risultati di un’altra query, sarebbe ansible (a seconda del dialetto SQL, su mssql sarebbe rownumber (), ma non so come in MySql, ma probabilmente è Là)

Ma non è quello che ti sento chiedere?

Dai uno sguardo alle domande SO seguenti:

  • Come generare un intervallo di numeri in Mysql
  • genera una sequenza intera in MySQL

Modificare:

Un altro approccio consiste nel creare una stored procedure che lo faccia per te. PostgreSQL contiene una funzione generate_series (start, stop) che fa ciò che vuoi.

 select * from generate_series(2,4); generate_series ----------------- 2 3 4 (3 rows) 

Non sono familiare con MySQL, ma qualcosa del genere dovrebbe essere facile da implementare, se stai bene con SP. Questo sito mostra un’attuazione.

Se il tuo database supporta funzioni di windowing analitico il seguente è semplice funziona molto bene:

 SELECT row_number() over (partition by 1 order by 1) numbers FROM SOME_TABLE LIMIT 2700; 

Questa affermazione restituisce un insieme di numeri da 1 a 2700.