2017-01-09 7 views
1

Ich möchte Sie fragen, wie ich ein bestimmtes Datum (DD-MON) aus dem Datumsbereich (DD-MON-YY) von Oracle SQL ermitteln kann? Das ist, was ich habe:Zähle spezifisches Datum im Datumsbereich in SQL

MEMBERS INSTALL_D DOB  SYSDATE 
6934109 22-FEB-12 18-NOV 09-JAN-17 
6934109 22-FEB-12 13-JUN 09-JAN-17 
6934109 22-FEB-12 12-AUG 09-JAN-17 
6934109 22-FEB-12 24-OCT 09-JAN-17 
6934109 22-FEB-12 04-FEB 09-JAN-17 

I DOB von Datumsbereich INSTALL_D und SYSDATE zählen möchten. Lassen Sie uns sagen, dass die

  1. Reihe mit 18 NOV 5 mal erscheinen wird,
  2. Reihe mit 13-Juni ist 5 mal erscheinen,
  3. Reihe mit 12-August ist 5 mal erscheinen,
  4. Reihe mit 24-OCT ist apeear 5 mal

und das letzte ist nur 4 mal.

so sollte das Ergebnis wie:

MEMBERS INSTALL_D DOB  SYSDATE COUNT(DOB) 
6934109 22-FEB-12 18-NOV 09-JAN-17 5 
6934109 22-FEB-12 13-JUN 09-JAN-17 5 
6934109 22-FEB-12 12-AUG 09-JAN-17 5 
6934109 22-FEB-12 24-OCT 09-JAN-17 5 
6934109 22-FEB-12 04-FEB 09-JAN-17 4 

I MONTHS_BETWEEN Funktion versucht, aber das ist nicht das, was ich bekommen möchten.

EDIT:
Ich werde genauer sein. Ich habe diese Abfrage die erste Tabelle oben zu bekommen:
select B0022HOME_NO as Members, B0022INSTALLDATE as INSTALL_DATE, to_char(to_date (encryption.decrypt(a.B0031MEMDATEOFBIRT),'DD-MON-YYYY'),'DD-MON')as DOB, SYSDATE from BT0022, BT0031 a where B0022HOME_NO=a.B003101HOME_NO and BT0022.B0022HOME_NO=6934109;

INSTALL_D Tag der Instalation ist, die in diesem Beispiel 22-FEB-12
DOB Geburtstag Mitglied ist. Nur Tag und Monat (DD-MON)
SYSDATE ist für das aktuelle Datum. Nehmen wir an, wenn das Sysdate 18-NOV-12 und INSTALL_D 22-FEB-12 und DOB des Elements 18-NOV ist, bedeutet das, dass das DOB einmal in diesem Datumsbereich auftritt.
Im Beispiel: INSTALL_D 22-FEB-12 und SYSDATE 09-JAN-17 ist DOB von 18-NOV auftreten 5 mal, aber wenn das SYSDATE 18-NOV-17 sein wird, wird es 6-mal. Und genau darum habe ich dich im Datumsbereich nach Count (DOB) gefragt.

Vielen Dank im Voraus

+0

Spaltendatentypen? Welche DBMS verwendest du? – jarlh

+0

INSTALL_D-Spalte ist DATE-Typ und DOB ist varchar2. DBMS ist Oracle Database 10g Release 10.2.0.1.0 - 64bit – Matej

+0

Severa Probleme mit diesem Setup. Warum ist "SYSDATE" eine Spalte in dieser Tabelle? SYSDATE ist eine Systemfunktion, ihr Wert wird im laufenden Betrieb berechnet, sie wird nicht in Tabellen gespeichert. Wollten Sie SYSDATE verwenden (aber haben Sie dafür keine Spalte in der Tabelle) oder wollten Sie ein gespeichertes Datum verwenden, das nicht als "SYSDATE" bezeichnet werden sollte? Dann - wollten Sie die Spalte MITGLIEDER so ändern, dass Sie nicht den gleichen Wert in allen Zeilen haben? (Ich nehme nicht an, dass das gleiche Mitglied unterschiedliche Geburtsdaten hat). Warum wird das DOB auch als VARCHAR2 gespeichert, anstatt ein Datum (einschließlich des Jahres) zu sein? – mathguy

Antwort

1

Hier ist eine andere Art und Weise, die hoffentlich mit dob ​​Wille arbeiten, die in Schaltjahren auftreten : Nb Ich habe angenommen, dass alle Ihre Daten als DATEs gespeichert sind, was bedeutet, dass Ihre Dob-Spalte Jahre hat. Wenn das nicht der Fall ist, dann a) warum speichern Sie nicht das Jahr mit dem d ob? und b) Sie müssen meine Abfrage aktualisieren, um die Zeichenfolge in ein geeignetes Format für den Vergleich zu konvertieren)

WITH sample_data AS (SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('18/11/1969', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('13/06/1991', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('12/08/1982', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('24/10/1963', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934109 members, to_date('22/02/2012', 'dd/mm/yyyy') install_d, to_date('04/02/1975', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934110 members, to_date('28/02/2011', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934110 members, to_date('29/02/2012', 'dd/mm/yyyy') install_d, to_date('01/03/1975', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934111 members, to_date('01/01/2017', 'dd/mm/yyyy') install_d, to_date('12/01/1957', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934111 members, to_date('01/01/2017', 'dd/mm/yyyy') install_d, to_date('02/01/1980', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934112 members, to_date('01/03/2011', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual UNION ALL 
        SELECT 6934112 members, to_date('29/02/2012', 'dd/mm/yyyy') install_d, to_date('29/02/1976', 'dd/mm/yyyy') dob FROM dual) 
SELECT members, 
     install_d, 
     dob, 
     SYSDATE, 
     date_of_first_year, 
     date_of_latest_year, 
     months_between(date_of_latest_year, date_of_first_year)/12 + 1 count_birthdays 
FROM (SELECT members, 
       install_d, 
       dob, 
       SYSDATE, 
       CASE WHEN to_char(dob, 'mmdd') < to_char(install_d, 'mmdd') THEN 
         trunc(add_months(install_d, 12), 'yyyy') 
        ELSE trunc(install_d, 'yyyy') 
       END date_of_first_year, 
       CASE WHEN to_char(dob, 'mmdd') <= to_char(SYSDATE, 'mmdd') THEN 
         trunc(SYSDATE, 'yyyy') 
        ELSE add_months(trunc(SYSDATE, 'yyyy'), -12) 
       END date_of_latest_year 
     FROM sample_data); 

    MEMBERS INSTALL_D DOB   SYSDATE  DATE_OF_FIRST_YEAR DATE_OF_LATEST_YEAR COUNT_BIRTHDAYS 
---------- ----------- ----------- ----------- ------------------ ------------------- --------------- 
    6934109 22/02/2012 18/11/1969 09/01/2017 01/01/2012   01/01/2016      5 
    6934109 22/02/2012 13/06/1991 09/01/2017 01/01/2012   01/01/2016      5 
    6934109 22/02/2012 12/08/1982 09/01/2017 01/01/2012   01/01/2016      5 
    6934109 22/02/2012 24/10/1963 09/01/2017 01/01/2012   01/01/2016      5 
    6934109 22/02/2012 04/02/1975 09/01/2017 01/01/2013   01/01/2016      4 
    6934110 28/02/2011 29/02/1976 09/01/2017 01/01/2011   01/01/2016      6 
    6934110 29/02/2012 01/03/1975 09/01/2017 01/01/2012   01/01/2016      5 
    6934111 01/01/2017 12/01/1957 09/01/2017 01/01/2017   01/01/2016      0 
    6934111 01/01/2017 02/01/1980 09/01/2017 01/01/2017   01/01/2017      1 
    6934112 01/03/2011 29/02/1976 09/01/2017 01/01/2012   01/01/2016      5 
    6934112 29/02/2012 29/02/1976 09/01/2017 01/01/2012   01/01/2016      5 

Das einzige Haar in der Suppe tritt auf, wenn Sie einen dob von 29. Februar wollen 1. anzupassen von März auf Nicht-Schaltjahren.

Meine Abfrage oben enthält diese Logik nicht, aber Sie könnten immer eine Prüfung hinzufügen, um den letzten Tag des Februar in den Jahren install_d und sysdate zu vergleichen, und wenn es 28 ist, dann ändern Sie ein dob von '29/02 'bis '01/03' vor diesem Vergleich. (Vergleiche install_d vom 29/02/2012 mit dob ​​= 29/02, da 2012 ein Schaltjahr ist. Sie müssen das sysdate nicht vergleichen, da 0301> = 0229 und 0228 < 0229, ob das sysdate ein ist Schaltjahr oder nicht.)

+0

Hmm ... interessantes Thema, über das ich vorher noch nicht nachgedacht habe. Der Dob eines "leaper" hat legale Bedeutung (zB wann darf ein "leaper" einen Führerschein bekommen?) Ich nahm immer an, dass es am 28. Februar in Nicht-Schaltjahren wäre, aber Wikipedia zeigt das in vielen Gerichtsbarkeiten ist der 1. März. Das ergibt für mich keinen Sinn. Der Schalttag ist der 29. Februar, weil er erfunden wurde, als das Kalenderjahr noch am 1. März begann. (SEPember war der 7. Monat, OKTober der 8. usw.) Also 29. Februar ist auch der letzte Tag eines Jahres, nicht nur ein Monat. Wenn es nicht da ist, warum verschieben Sie den Jahrestag in ein anderes Jahr? – mathguy

+0

@mathguy Ich habe immer den 1. März angenommen, weil: (letzter Tag im Februar) + 366 Tage = 29. Februar (in einem Schaltjahr) oder 1. März (in einem Nicht-Schaltjahr) – Boneist

+0

'add_months()', zum Beispiel doesn verwende diese Logik nicht. Es entspricht Monatsende bis Monatsende, unabhängig von 30 oder 31. Da wir "um einen Tag frei haben" müssen, wäre es für mich sinnvoller, wenn mindestens der Monat (und das Kalenderjahr vor Julius Caesar) wäre erhalten, anstatt das Datum in den nächsten Monat und das "Jahr" zu verschieben. Aber was für mich Sinn macht, ist natürlich irrelevant; Wenn der OP dies für etwas anderes als persönliche Belustigung benutzt, sollte er klarstellen, was die geschäftliche (vielleicht gesetzliche) Anforderung ist. Interessantes Thema auf jeden Fall! – mathguy

0

Sie Gruppe von Datum Segmenten können, es ist nicht die schönste Sache, sondern arbeiten. z.B.

GROUP BY CAST(DATEPART(mm, dob) AS VARCHAR(2)) + '-' + CAST(DATEPART(yyyy, dob) AS VARCHAR(4)) 

Sie auch, dass in der select-Anweisung platzieren konnte

0

Versuchen Sie diese: (Gruppe arbeiten sollte)

SELECT MEMBERS,INSTALL_D,DOB,SYSDATE,Count(DOB) FROM table_name GROUP BY DOB ,MEMBERS,INSTALL_D ,SYSDATE 
Verwandte Themen