2016-08-30 4 views
0

Ich habe zwei Eingabedaten als Parameter und meine Abfrage sollte die letzten Quartalsenddaten zwischen zwei Daten zurückgeben. Wir haben vier Viertel in einem Jahr.SQL-Abfrage, um das letzte Quartalsenddatum für den Datumsbereich zu finden

Q1 -Jan to March 
Q2-Apr to June 
Q3-Jul to Sep 
Q4-Oct to Dec 

Eingang Q1-2015 Daten, Q2-2016

Anzahl der Daten von der Abfrage

Dec 31st 2014 
March 31st 2015 
June 30 2015 
Sep 30 2015 
Dec 31st 2015 
March 31st 2016 

Eingangs Termine Q1-2016 Q2-2016 zurückgegeben werden

Number of Dates to be returned from query 
Dec 31st 2015 
March 31 2016 

Ich brauche es in einer Abfrage zurückgegeben werden. Danke für Ihre Hilfe.

+0

Bitte fügen Sie einige Beispieldaten aus Ihrer Tabelle hinzu, um mit Ihrer erwarteten Ausgabe zu gehen. –

Antwort

0

Die folgende Lösung verwendet die Eingaben als Bindevariablen. Es funktioniert NUR, wenn die Eingaben genau in diesem Format sind (eine Zeichenfolge mit sieben Zeichen 'Qx-yyyy', wobei x von 1 bis 4 ist und yyyy ein gültiges Jahr ist) und NUR wenn das "to-viertel" gleich oder später als das "from" ist -Quartal"; Meine Lösung führt keine Validierung durch, um sicherzustellen, dass dies der Fall ist, und das Verhalten, wenn diese Regeln verletzt werden, ist undefiniert (was bedeutet, dass ich keine Zeit damit verbracht habe, "regelbrechende" Fälle zu testen).

with 
    prep (from_qtr, from_yr, to_qtr, to_yr) as (
     select to_number(substr(:from_year, 2, 1)), 
       to_number(substr(:from_year, 4 )), 
       to_number(substr(:to_year , 2, 1)), 
       to_number(substr(:to_year , 4 )) 
     from dual 
    ) 
select add_months(to_date(to_char(from_yr) || '/' || to_char(3 * from_qtr - 2) 
           || '/01', 'yyyy/mm/dd') - 1, 
        3 * (level - 1) 
       ) as qtr_end_date 
from prep 
connect by level <= 1 + 4 * (to_yr - from_yr) + (to_qtr - from_qtr) 
order by qtr_end_date 
; 

HINWEIS: Wenn Sie keine Verbindung herstellen-by-Ebene verwenden können, Sie ohne es tun können, aber Sie werden einen Mechanismus zu erzeugen Zahlen von 1 auf ein ausreichend hohes Limit benötigen. Sie können entweder eine num Tabelle (ähnlich der folgenden) fest codieren oder einen Mechanismus verwenden, um Zeilennummern aus einer Tabelle mit vielen Zeilen zu lesen. Hier ist eine mögliche Lösung:

with 
    prep (from_qtr, from_yr, to_qtr, to_yr) as (
     select to_number(substr(:from_year, 2, 1)), 
       to_number(substr(:from_year, 4 )), 
       to_number(substr(:to_year , 2, 1)), 
       to_number(substr(:to_year , 4 )) 
     from dual 
    ), 
    num (rn) as (select rownum from all_tab_columns) 
select add_months(to_date(to_char(from_yr) || '/' || to_char(3 * from_qtr - 2) 
           || '/01', 'yyyy/mm/dd') - 1, 
        3 * (rn - 1) 
       ) as qtr_end_date 
from prep cross join num 
where rn <= 1 + 4 * (to_yr - from_yr) + (to_qtr - from_qtr) 
order by qtr_end_date 
; 

Die hartcodierte Alternative ist num (rn) as select 1 from dual union all select 2 from dual union all select 3 from dual ...... ) zu sagen, und Sie müssen eine ausreichende Zahl müssen alle möglichen Fälle abzudecken.

+0

Hallo, das ist was genau benötigt, ich suche in Sybase.do haben wir in Sybase verbinden. – user3200735

+0

Ich spreche nur Oracle. Wenn Sie Sybase verwenden, warum ist Ihr Beitrag mit "oracle" markiert? – mathguy

+0

Hallo, habe nicht gefunden Tag für Sybase, so dachte ich kann in Sybase schreiben, wenn ich in Orakel, können wir dies ohne Verwendung von connect von ändern, aber die Ausgabe dieser Abfrage ist korrekt, ich eingecheckt in Oracle.Same Logik ohne Verbindung durch Können wir erreichen – user3200735

0

Dies ist, was genau benötigt wird, ich suche in Sybase.do haben wir in Sybase verbinden.

Verwandte Themen