2009-03-31 12 views
18

Y at-il un moyen de générer un nombre arbitraire de lignes qui peuvent être utilisés dans une jointure similaire à la syntaxe Oracle:Comment créer un générateur de lignes dans MySQL?

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

Pourriez-vous s'il vous plaît poster la requête que vous vouliez écrire ? –

Répondre

22

Haine de le dire, mais MySQL est le seul RDBMS du grand quatre qui n'a pas cette fonctionnalité.

Dans Oracle:

SELECT * 
FROM dual 
CONNECT BY 
     level < n 

Dans MS SQL (jusqu'à 100 lignes):

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

ou en utilisant soupçon jusqu'à 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 

Dans PostgreSQL:

SELECT * 
FROM generate_series (1, n) 

En MySQL, rien.

+4

Reg MySQL: Espérons que comble un peu le fossé: http://use-the-index-luke.com/blog/2011-07-30/mysql -row-generator # mysql_generator_code –

0

Avez-vous envisagé une jointure externe gauche?

+1

Oui, le problème est que j'ai besoin de quelque chose pour faire le JOIN contre – GameFreak

0

Je ne sais pas si cela vous aide, mais vous pouvez numéroter les lignes de chaque instruction select avec sth. comme:

SET @NUM = 0;

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

Et ensuite les rejoindre sur celui-ci. Dans les grandes bases de données, cela peut être très lent.

0

Si je vous comprends, vous voulez une liste de nombres conséquents?

Il suffit de faire la liste:

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, jusqu'à ce que vous avez, disons, 1024.

update artificial_range set idn = id - 1 ; 

- vous avez maintenant une série à regarder 1 (id) et une série à partir de 0

maintenant se joindre à elle, ou se joindre à des transformations de celui-ci:

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

c'était exactement ce que j'espérais éviter. – GameFreak

8

Dans MySQL, je comprends que vous pouvez obtenir plus d'une ligne avec un SELECT sans table (ou DUAL).

Par conséquent, pour obtenir plusieurs lignes, do besoin d'une table réelle ou temporaire avec au moins le nombre requis de lignes.

Cependant, vous n'avez pas besoin de construire une table temporaire que vous pouvez utiliser TOUT table existante qui a au moins le nombre de lignes nécessaires.Donc, si vous avez une table avec au moins le nombre requis de lignes, utilisez:

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

Il suffit de remplacer « sometable » avec le nom d'une table de la vôtre avec au moins le nombre requis de lignes. PS: Le "r" est un tableau "alias": j'aurais pu utiliser "AS r". Toute sous-requête dans une clause FROM ou JOIN crée une "table dérivée" qui, comme toutes les tables, doit avoir un nom ou un alias. (Voir manuel MySql: 13.2.9.8 Sous-requêtes dans la clause FROM)

0

J'avais une table avec une colonne (c5) qui contenait un nombre x, j'avais besoin d'une expression SQL qui répétait la même ligne x nombre de fois.

Mon tableau A contient:

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

et moi avions besoin:

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 

Je résolus que par l'expression:

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; 
Questions connexes