2009-03-31 9 views
18

¿Hay una manera de generar un número arbitrario de filas que se pueden utilizar en una unión similar a la sintaxis de Oracle:¿Cómo puedo hacer un generador de filas en MySQL?

SELECT LEVEL FROM DUAL CONNECT BY LEVEL<=10 
+0

¿Podría por favor puesto la consulta que significa que escribir ? –

Respuesta

22

Odia decir esto, pero MySQL es el único RDBMS de los cuatro grandes que no tiene esta característica.

En Oracle:

SELECT * 
FROM dual 
CONNECT BY 
     level < n 

En MS SQL (hasta 100 filas):

WITH hier(row) AS 
     (
     SELECT 1 
     UNION ALL 
     SELECT row + 1 
     FROM hier 
     WHERE row < n 
     ) 
SELECT * 
FROM hier 

o usando indirecta hasta 32768

WITH hier(row) AS 
     (
     SELECT 1 
     UNION ALL 
     SELECT row + 1 
     FROM hier 
     WHERE row < 32768 
     ) 
SELECT * 
FROM hier 
OPTION (MAXRECURSION 32767) -- 32767 is the maximum value of the hint 

En PostgreSQL:

SELECT * 
FROM generate_series (1, n) 

En MySQL, nada.

+4

Reg MySQL: Espero que llene la brecha un poco: http://use-the-index-luke.com/blog/2011-07-30/mysql -row-generator # mysql_generator_code –

0

¿Ha considerado un LEFT OUTER JOIN?

+1

Sí, el problema es que necesito algo para hacer el JOIN contra – GameFreak

0

No sé si esto ayuda, pero puede numerar las filas de cada instrucción de selección con sth. como:

SET @NUM = 0;

@NUM SELECT: @ = NUM ​​+ 1 rowNumber, * FROM ...

Y más tarde se unen a ellos en este caso. En bases de datos grandes esto puede ser muy lento.

0

Si te entiendo, ¿quieres una lista de números consecutivos?

Sólo hacer la lista:

create table artificial_range (id int not null primary key auto_increment, idn int); 
insert into artificial_range (idn) values (0); --first row 
insert into artificial_range(idn) select idn from artificial_range; --2nd 
insert into artificial_range(idn) select idn from artificial_range; -- now 4 rows 
insert into artificial_range(idn) select idn from artificial_range; --8 
insert into artificial_range(idn) select idn from artificial_range; --16 
insert into artificial_range(idn) select idn from artificial_range; --32 
insert into artificial_range(idn) select idn from artificial_range; --64 
insert into artificial_range(idn) select idn from artificial_range; --128 

... etc, hasta que tenga, digamos, 1024.

update artificial_range set idn = id - 1 ; 

- ahora usted tiene una serie mirando a 1 (ID) y una serie a partir de 0

ahora unirse a ella, o unirse a las transformaciones de la misma:

create view days_this_century as 
select date_add('2000-01-01', interval a.idn day) as cdate 
from artificial_range; 
+3

eso era exactamente lo que esperaba evitar. – GameFreak

8

En MySql, entiendo que puede obtener más de una fila con SELECT sin tabla (o DUAL).

Por lo tanto, para obtener varias filas, do necesita una tabla real o temporal con al menos el número requerido de filas.

Sin embargo, que no es necesario construir una tabla temporal como se puede usar CUALQUIER tabla existente que tiene al menos el número de filas necesarias.Por lo tanto, si usted tiene una tabla con al menos el número requerido de filas, utilice:

SELECT @curRow := @curRow + 1 AS row_number 
FROM sometable 
JOIN (SELECT @curRow := 0) r 
WHERE @curRow<100; 

Basta con sustituir "alguna_tabla" con el nombre de cualquier tabla de los suyos con al menos el número requerido de filas.

PD: La "r" es una tabla "alias": podría haber usado "AS r". Cualquier subconsulta en una cláusula FROM o JOIN crea una "tabla derivada" que, como todas las tablas, debe tener un nombre o alias. (Consulte el manual de MySql: 13.2.9.8. Subconsultas en la Cláusula FROM)

0

Tenía una tabla con una columna (c5) que contenía un número x, necesitaba una expresión SQL que repitiera la misma fila x números de veces.

Mi tabla A contenía:

c1 c2 c3 c4 c5 
16 1 2 16 3 
16 1 2 17 2 
16 1 2 18 1 

y necesitaba:

c1 c2 c3 c4 c5 n 
16 1 2 16 3 1 
16 1 2 16 3 2 
16 1 2 16 3 3 
16 1 2 17 2 1 
16 1 2 17 2 2 
16 1 2 18 1 1 

He resuelto que con la expresión:

SELECT 
    c1, c2, c3, c4, c5, row_number AS n 
FROM 
    (
     SELECT 
      @curRow := @curRow + 1 AS row_number 
     FROM 
      tablea 
     JOIN (SELECT @curRow := 0) r 
     WHERE 
      @curRow < (
       SELECT 
        max(field1) 
       FROM 
        tablea 
      ) 
    ) AS vwtable2 
LEFT JOIN tablea d ON vwtable2.row_number <= tablea.field1; 
Cuestiones relacionadas