Erstellen Sie eine inkrementelle Zahl in einer Oracle SQL-Abfrage

13

Wie erstelle ich eine inkrementelle Zahl in einer Oracle SQL-Abfrage, ohne eine Tabelle zu erstellen? Ich habe versucht, die "with" -Klausel zu verwenden, aber ich konnte das erwartete Ergebnis nicht erzielen. Ich benutze Orakel 10g

Hier ist der Code, den ich versuche, es scheint nicht zu funktionieren:

WITH
TABLE3 AS ( SELECT 2008 YEARS FROM dual WHERE 1=1
union all
select t3.YEARS+1 from TABLE3 t3
WHERE 1=1 AND t3.YEARS < 2011
)

select YEARS from TABLE3

Das erwartete Ergebnis ist:

2008
2009
2010
2011
50LV3R
quelle

Antworten:

14

Ähnlich wie Kerris Antwort, aber ohne die with(und inspiriert von einer SO-Antwort ):

SELECT 2007 + LEVEL AS YEARS
FROM DUAL
CONNECT BY LEVEL <= 4;

     YEARS
----------
      2008
      2009
      2010
      2011

Oder wenn Sie das aktuelle Jahr mit den drei vorangestellten erhalten möchten, ohne das Startjahr fest zu codieren:

SELECT EXTRACT(YEAR FROM SYSDATE) + 1 - LEVEL AS YEARS
FROM DUAL
CONNECT BY LEVEL <= 4
ORDER BY YEARS;
Alex Poole
quelle
1
Ich denke, ich werde dieses für meinen Code auswählen, es ist viel einfacher als die Verwendung von With-Klausel
50LV3R
16

Ich denke, dies wird funktionieren (basierend auf dieser Seite ( http://psoug.org/definition/LEVEL.htm ) als Ausgangspunkt):

WITH counter
AS ( SELECT LEVEL seq
       FROM DUAL
     CONNECT BY LEVEL <= 4 )
SELECT (2008 + seq - 1) myYear
  FROM counter
 ORDER BY 1
;

Dies sollte zurückgeben:

myYear
------
  2008
  2009
  2010
  2011

Passen Sie 2008 und 4 an, um unterschiedliche Ergebnisse zu erhalten.

Kerri Shotts
quelle
5

Offenbar hat das OP versucht, das Problem mithilfe einer rekursiven Unterabfrage zu lösen. Dies wird in 10g nicht funktionieren, da diese Funktionalität erst in 11.2 hinzugefügt wurde, aber in 11.2+ wäre das Folgende auch eine gültige Lösung für das Problem.

WITH T3(Years) AS (
   SELECT 2008 Years FROM dual
   UNION ALL
   SELECT Years + 1 FROM T3 WHERE Years < 2011
   )
SELECT * FROM T3;

Das einzige, was in der OP-Abfrage fehlte, war (YEARS).

Leigh Riffel
quelle
Leicht modifizierte Werke auch in MS SQL WITH T3(Years) AS ( SELECT 2008 Years UNION ALL SELECT Years + 1 FROM T3 WHERE Years < 2011 ) SELECT * FROM T3;
miracle173
@ miracle173 Interessant, einfach den entfernen FROM dual.
Leigh Riffel
dualist eine Orakel-spezifische Tabelle. Andere Datenbanken wie MS SQL Server, MySQL, Postgres erlauben Anweisungen wie select expression. Mysql kennt die eine duale Tabelle auch
miracle173
4

Warum nicht einfach eine Sequenz erstellen?

CREATE SEQUENCE TEMP_YEAR_sEQUENCE START WITH 2008;

SELECT TEMP_YEAR_sEQUENCE.NEXTVAL FROM DUAL; 

....

DROP SEQUENCE TEMP_YEAR_SEQUENCE;

BEARBEITEN:

Für kleine Bereiche von Sequenzwerten können Sie Folgendes verwenden:

select ROWNUM + 10   # start value
from ALL_OBJECTS 
where ROWNUM <= 5 ;  # count of values 

Sie brauchen nur eine Tabelle mit einer ausreichenden Anzahl von Zeilen.

bernd_k
quelle
3
Es scheint viel Aufwand für etwas so Triviales zu sein, und die DDL führt ein implizites Commit aus, das möglicherweise nicht erwartet wird. Der Benutzer, der die Abfrage ausgibt, verfügt möglicherweise nicht über die Berechtigung zum Erstellen einer Sequenz.
Alex Poole
Ich bin mit Alex Poole einverstanden, aber es ist trotzdem ein weiterer Workaround, danke
50LV3R
-1 aus den angegebenen Gründen @AlexPoole. Wenn Sie die Abfrage erneut ausführen, ohne die Sequenz neu zu erstellen, erhalten Sie ein anderes Ergebnis.
miracle173
Die Abfrage, die die Sequenz verwendet, gibt den gewünschten Satz von Zahlen nicht zurück.
miracle173
-1

Hier ist ein Beispiel für das Hinzufügen mehrerer Flags und das Inkrementieren dieser anhand der case-Anweisung.

WITH T3(FLAG1,FLAG2,FLAG3,tt,OTHER_DATA)  
AS (    
SELECT '0' FLAG1, '0' FLAG2, '0' FLAG3 , current_timestamp  tt , 'dummy'  OTHER_DATA 
FROM dual 
UNION ALL  
SELECT case when cast( FLAG2 as int) > 5 then
cast ((cast(FLAG1 as int) + 1) as varchar2(30)) else  FLAG1 end FLAG1,
cast((cast(FLAG2 as int) + 1) as varchar2(30)) FLAG2  ,case when (
(FLAG2 ='3') or (FLAG2 = '4')) then cast ((cast(  FLAG3 as int) + 1)
as varchar2(30)) else FLAG3 end FLAG3  ,current_timestamp  tt ,
'ACTUAL' OTHER_DATA FROM T3 WHERE FLAG2 < 10   
)
SELECT * FROM T3
WHERE OTHER_DATA != 'dummy' ;

- Die Ergebnismenge ist unten

Flag1   Flag2   Flag3   TT                                              OTHER_DATA
0       1       0       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
0       2       0       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
0       3       0       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
0       4       1       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
0       5       2       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
0       6       2       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
1       7       2       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
2       8       2       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
3       9       2       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL
4      10       2       21-DEC-15 08.31.05.229502000 PM ASIA/CALCUTTA   ACTUAL   
Suyaraj Mariappan
quelle
2
Warum all das Casting zwischen Strings und Zahlen? Ich bin mir nicht ganz sicher, was dies zu den vorhandenen Antworten beiträgt, da das OP nicht danach zu suchen schien.
Alex Poole
-1

Erhöhen Sie nur in einem mit dem Rownum Wählen Sie Rownum + 100 aus "Tabelle" Reihenfolge um 1;

Das Ergebnis mit 101, 102 usw.

L.Luca
quelle