Est-il possible de sélectionner les nombres (nombres entiers) inclus entre deux nombres avec SQL dans Oracle? Je ne veux pas créer de procédure ou de fonction PL/SQL.
Par exemple, je dois obtenir les nombres entre 3 et 10. Le résultat sera les valeurs 3,4,5,6,7,8,9,10.
THX.
Cette astuce avec la table DUAL d’Oracle fonctionne également:
SQL> select n from
2 ( select rownum n from dual connect by level <= 10)
3 where n >= 3;
N
----------
3
4
5
6
7
8
9
10
La première chose que je fais lorsque je crée une nouvelle base de données consiste à créer et à remplir des tables de base.
L'un est une liste de tous les entiers compris entre -N et N, un autre est une liste des dates 5 à 10 ans dans le futur (un travail planifié peut continuer de les créer si nécessaire, à l'avenir) et le dernier est une liste. de toutes les heures de la journée. Par exemple, les inetgers:
create table numbers (n integer primary key);
insert into numbers values (0);
insert into numbers select n+1 from numbers; commit;
insert into numbers select n+2 from numbers; commit;
insert into numbers select n+4 from numbers; commit;
insert into numbers select n+8 from numbers; commit;
insert into numbers select n+16 from numbers; commit;
insert into numbers select n+32 from numbers; commit;
insert into numbers select n+64 from numbers; commit;
insert into numbers select n+128 from numbers; commit;
insert into numbers select n+256 from numbers; commit;
insert into numbers select n+512 from numbers; commit;
insert into numbers select n+1024 from numbers; commit;
insert into numbers select n+2048 from numbers; commit;
insert into numbers select n+4096 from numbers; commit;
insert into numbers select n+8192 from numbers; commit;
insert into numbers select -n from numbers where n > 0; commit;
Ceci concerne DB2/z qui a le démarrage automatique de la transaction, raison pour laquelle il semble avoir des commits nus.
Oui, cela prend un espace (minimal) mais cela rend les requêtes beaucoup plus faciles à écrire, simplement en sélectionnant des valeurs dans ces tables. Il est également très portable dans presque tous les n'importe quel SGBD basé sur SQL.
Votre requête particulière serait alors simple:
select n from numbers where n >=3 and n <= 10;
Les chiffres des heures et les plages de dates sont très utiles pour le type d'applications de création de rapports sur lequel nous travaillons. Cela nous permet de ne créer aucune entrée pour les heures du jour (ou les dates) qui ne contiennent pas de données réelles. Ainsi, au lieu de (lorsqu'il n'y a pas de données le deuxième jour du mois):
Date | Quantity
-----------+---------
2009-01-01 | 7
2009-01-03 | 27
2009-01-04 | 6
nous pouvons plutôt obtenir:
Date | Quantity
-----------+---------
2009-01-01 | 7
2009-01-02 | 0
2009-01-03 | 27
2009-01-04 | 6
Vous pouvez utiliser la clause MODEL pour cela.
SELECT c1 from dual
MODEL DIMENSION BY (1 as rn) MEASURES (1 as c1)
RULES ITERATE (7)
(c1[ITERATION_NUMBER]=ITERATION_NUMBER+7)
SQL> var N_BEGIN number
SQL> var N_END number
SQL> exec :N_BEGIN := 3; :N_END := 10
PL/SQL procedure successfully completed.
SQL> select :N_BEGIN + level - 1 n
2 from dual
3 connect by level <= :N_END - :N_BEGIN + 1
4 /
N
----------
3
4
5
6
7
8
9
10
8 rows selected.
Cela utilise le même truc que Tony. Notez que lorsque vous utilisez SQL * Plus 9, vous devez transformer cette requête en vue intégrée, comme l’a montré Tony. Dans SQL * Plus 10 ou supérieur, ce qui précède est suffisant.
Cordialement, .__ Rob.
cette requête d'une seule ligne vous aidera,
select level lvl from dual where level<:upperbound and
level >:lowerbound connect by level<:limt
Pour votre cas:
select level lvl from dual where level<10 and level >3 connect by level<11
laissez-moi savoir si des éclaircissements.
Ou vous pouvez utiliser Entre
Select Column1 from dummy_table where Column2 Between 3 and 10
Une façon de générer des nombres à partir d'une plage consiste à utiliser XMLTABLE('start to end')
:
SELECT column_value
FROM XMLTABLE('3 to 10');
C'est un ajout tardif. Mais la solution semble être plus élégante et plus facile à utiliser.
Il utilise une fonction pipelined qui doit être installée une fois:
CREATE TYPE number_row_type AS OBJECT
(
num NUMBER
);
CREATE TYPE number_set_type AS TABLE OF number_row_type;
CREATE OR REPLACE FUNCTION number_range(p_start IN PLS_INTEGER, p_end IN PLS_INTEGER)
RETURN number_set_type
PIPELINED
IS
out_rec number_row_type := number_row_type(NULL);
BEGIN
FOR i IN p_start .. p_end LOOP
out_rec.num := i;
pipe row(out_rec);
END LOOP;
END number_range;
/
Ensuite, vous pouvez l'utiliser comme ceci:
select * from table(number_range(1, 10));
NUM
---
1
2
3
4
5
6
7
8
9
10
La solution est spécifique à Oracle.
Gary, pour montrer le résultat qu'il a expliqué, la requête modèle sera:
CHOISISSEZ c1 DANS DOUBLE MODÈLE DIMENSION DE (1 comme rn)
MESURES (1 comme c1) RÈGLES ITERATE (8) (C1 [NOMBRE ITERATION] = NOMBRE ITERATION + 3).
;)
J'utilise toujours:
SELECT (LEVEL - 1) + 3 comme résultat FROM Dual CONNECT BY Level <= 8
Où 3 est le numéro de départ et 8 le nombre "d'itérations".
Je viens de faire une fonction table évaluée à faire cela dans le serveur SQL, si quelqu'un est intéressé, cela fonctionne parfaitement.
CREATE FUNCTION [dbo].[NumbersBetween]
(
@StartN int,
@EndN int
)
RETURNS
@NumberList table
(
Number int
)
AS
BEGIN
WHILE @StartN <= @EndN
BEGIN
insert into @NumberList
VALUES (@StartN)
set @StartN = @StartN + 1
END
Return
END
GO
Si vous exécutez la requête: "select * from dbo.NumbersBetween (1,5)" (sans les guillemets bien sûr), le résultat sera
Number
-------
1
2
3
4
5
Je veux partager une requête utile qui convertit une chaîne de virgules et une liste de nombres séparés par «-» en une liste de nombres développée équivalente
Un exemple qui convertit '1,2,3,50-60' en
1 2 3 50 51 ... 60
select distinct * from (SELECT (LEVEL - 1) + mini as result FROM (select REGEXP_SUBSTR (value, '[^-]+', 1, 1)mini ,nvl(REGEXP_SUBSTR (value, '[^-]+', 1, 2),0) maxi from (select REGEXP_SUBSTR (value, '[^,]+', 1, level) as value from (select '1,2,3,50-60' value from dual) connect by level <= length(regexp_replace(value,'[^,]*'))+1)) CONNECT BY Level <= (maxi-mini+1)) order by 1 asc;
Vous pouvez l'utiliser comme une vue et paramétrer la chaîne '1,2,3,50-60'
create table numbers (value number);
declare
x number;
begin
for x in 7 .. 25
loop
insert into numbers values (x);
end loop;
end;
/