À l'aide du tableau DUAL, comment puis-je obtenir une liste de nombres de 1 à 100?
Votre question est difficile à comprendre, mais si vous voulez sélectionner les nombres de 1
à 100
, alors cela devrait faire l'affaire:
Select Rownum r
From dual
Connect By Rownum <= 100
Une autre solution intéressante dans Oracle PL/SQL:
SELECT LEVEL n
FROM DUAL
CONNECT BY LEVEL <= 100;
Faites-le à la dure. Utilisez la clause awesome MODEL
:
SELECT V
FROM DUAL
MODEL DIMENSION BY (0 R)
MEASURES (0 V)
RULES ITERATE (100) (
V[ITERATION_NUMBER] = ITERATION_NUMBER + 1
)
ORDER BY 1
La réponse de Peter est aussi ma préférée.
Si vous recherchez plus de détails, il y a un assez bon aperçu, IMO, here .
Il est particulièrement intéressant de lire les points de repère .
Si vous voulez que vos entiers soient liés entre deux entiers (c'est-à-dire, commencez par autre chose que 1), vous pouvez utiliser quelque chose comme ça:
with bnd as (select 4 lo, 9 hi from dual)
select (select lo from bnd) - 1 + level r
from dual
connect by level <= (select hi-lo from bnd);
Il donne:
4
5
6
7
8
À l'aide de la clause de sous-fabrique de requête d'Oracle "WITH", vous pouvez sélectionner des nombres de 1 à 100:
WITH t(n) AS (
SELECT 1 from dual
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT * FROM t;
Utiliser GROUP BY CUBE
:
SELECT ROWNUM
FROM (SELECT 1 AS c FROM dual GROUP BY CUBE(1,1,1,1,1,1,1) ) sub
WHERE ROWNUM <=100;
Voici un moyen amusant de générer une table numérique. Il n'utilise pas la table DUAL, mais si la table DUAL devait disparaître, il pourrait s'agir d'un plan de secours.
DECLARE @TotalNumbers INT = 100;
DECLARE @From DATETIME = CONVERT(DATETIME, CONVERT(DATE, GETDATE())),
@To DATETIME = DATEADD(SECOND, @TotalNumbers - 1, CONVERT(DATETIME, CONVERT(DATE, GETDATE())));
WITH AlmostNumberTable (Hola)
AS (SELECT @From
UNION ALL
SELECT DATEADD(SECOND, 1, Hola)
FROM AlmostNumberTable
WHERE Hola< @To
)
SELECT [Number]
FROM
(
SELECT DATEPART(MINUTE, AlmostNumberTable.Hola) * 60 + DATEPART(SECOND, AlmostNumberTable.Hola) + 1 AS [Number]
FROM AlmostNumberTable
) AS NumberTable;
C'est probablement un non-sens, mais c'est une solution qui fonctionne et c'était amusant d'écrire.
Une variante de l'exemple de Peter, qui montre comment l'utiliser pour générer tous les nombres compris entre 0 et 99.
with digits as (
select mod(rownum,10) as num
from dual
connect by rownum <= 10
)
select a.num*10+b.num as num
from digits a
,digits b
order by num
;
Cela devient utile lorsque vous effectuez une affectation d'identificateur de lot et que vous recherchez les éléments qui n'ont pas encore été attribués.
Par exemple, si vous vendez des billets de bingo, vous pouvez attribuer des lots de 100 personnes au sol (devinez comment je collectais des fonds pour le sport). Comme ils vendent un lot, ils reçoivent le prochain lot en séquence. Toutefois, les personnes qui achètent les billets peuvent choisir d'acheter n'importe quel billet du lot. La question peut être posée, "quels billets ont été vendus".
Dans ce cas, nous ne disposons que d’une liste partielle et aléatoire des tickets qui ont été renvoyés dans le même lot, et nous avons besoin d’une liste complète de toutes les possibilités pour déterminer ce que nous n’avons pas.
with range as (
select mod(rownum,100) as num
from dual
connect by rownum <= 100
),
AllPossible as (
select a.num*100+b.num as TicketNum
from batches a
,range b
order by num
)
select TicketNum as TicketsSold
from AllPossible
where AllPossible.Ticket not in (select TicketNum from TicketsReturned)
;
Excusez l'utilisation de mots-clés, j'ai changé certains noms de variables à partir d'un exemple réel.
... Pour démontrer pourquoi quelque chose comme cela serait utile
J'ai créé une fonction Oracle qui renvoie une table de nombres
CREATE OR REPLACE FUNCTION [schema].FN_TABLE_NUMBERS(
NUMINI INTEGER,
NUMFIN INTEGER,
EXPONENCIAL INTEGER DEFAULT 0
) RETURN TBL_NUMBERS
IS
NUMEROS TBL_NUMBERS;
INDICE NUMBER;
BEGIN
NUMEROS := TBL_NUMBERS();
FOR I IN (
WITH TABLA AS (SELECT NUMINI, NUMFIN FROM DUAL)
SELECT NUMINI NUM FROM TABLA UNION ALL
SELECT
(SELECT NUMINI FROM TABLA) + (LEVEL*TO_NUMBER('1E'||TO_CHAR(EXPONENCIAL))) NUM
FROM DUAL
CONNECT BY
(LEVEL*TO_NUMBER('1E'||TO_CHAR(EXPONENCIAL))) <= (SELECT NUMFIN-NUMINI FROM TABLA)
) LOOP
NUMEROS.EXTEND;
INDICE := NUMEROS.COUNT;
NUMEROS(INDICE):= i.NUM;
END LOOP;
RETURN NUMEROS;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN NUMEROS;
WHEN OTHERS THEN
RETURN NUMEROS;
END;
/
Est nécessaire créer un nouveau type de données:
CREATE OR REPLACE TYPE [schema]."TBL_NUMBERS" IS TABLE OF NUMBER;
/
Usage:
SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10))--integers difference: 1;2;.......;10
Et si vous avez besoin de nombres décimaux entre nombres par notation exponenciale:
SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10,-1));--with 0.1 difference: 1;1.1;1.2;.......;10
SELECT COLUMN_VALUE NUM FROM TABLE([schema].FN_TABLE_NUMBERS(1,10,-2));--with 0.01 difference: 1;1.01;1.02;.......;10