2017-11-09 2 views
0

I-Daten haben, die wie folgt aussieht:Muster identifizieren, um Gruppen zu erstellen

create table t (a varchar2(30), b date); 

insert into t values (NULL,TO_DATE('2017/01/01 00:00:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values (NULL,TO_DATE('2017/01/01 01:00:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values ('AAAA',TO_DATE('2017/01/01 02:00:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values (NULL,TO_DATE('2017/01/01 02:30:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values ('AAAA',TO_DATE('2017/01/01 03:00:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values (NULL,TO_DATE('2017/01/01 04:00:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values ('AAAA',TO_DATE('2017/01/01 04:30:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values (NULL,TO_DATE('2017/01/01 05:00:44', 'yyyy/mm/dd hh24:mi:ss')); 
insert into t values ('AAAA',TO_DATE('2017/01/01 05:30:44', 'yyyy/mm/dd hh24:mi:ss')); 

Ich brauche eine Gruppennummer für jede sich wiederholende Muster des Textfeldes zuzuordnen. Das Muster, nach dem ich suche, ist "AAAA - null - AAAA". Ich möchte in der Lage sein, andere "Nullen" außerhalb dieses Musters zu ignorieren. Im Wesentlichen suchen eine Gruppennummer wie folgt vergeben:

a   b    GROUP 
(null)  1/1/2017 0:00 IGNORE FROM ASSIGNING GROUP # 
(null)  1/1/2017 1:00 IGNORE FROM ASSIGNING GROUP # 
AAAA  1/1/2017 2:00  1 
(null)  1/1/2017 2:30  1 
AAAA  1/1/2017 3:00  1 
(null)  1/1/2017 4:00 IGNORE FROM ASSIGNING GROUP # 
AAAA  1/1/2017 4:30  2 
(null)  1/1/2017 5:00  2 
AAAA  1/1/2017 5:30  2 

ich die Daten wie wie folgt aussehen würde:

a  b    GROUP 
AAAA  1/1/2017 2:00 1 
(null) 1/1/2017 2:30 1 
AAAA  1/1/2017 3:00 1 
AAAA  1/1/2017 4:30 2 
(null) 1/1/2017 5:00 2 
AAAA  1/1/2017 5:30 2 

Oracle SQL-Version:

Oracle Database 11g 11.2.0.4 .0 PL/SQL Release 11.2.0.4.0

+0

Sie haben etwas probiert? –

+0

In der mittleren Tabelle hast du 'IGNORE FROM ASSIGNING GROUP #' geschrieben, aber dann in der Ausgabe, die du zeigst, sind diese Zeilen ** nicht enthalten **. Sie werden nicht nur "aus der Gruppennummer" ignoriert, sie werden in ihrer Gesamtheit ignoriert. Also, was ist Ihre Anforderung - schließen Sie diese Zeilen vollständig aus der Ausgabe aus? Dann: Was muss mit Zeilen gemacht werden, wenn der Text in der Spalte "a" nicht null ist, dann haben einige Zeilen "null", und dann gibt es in der Spalte "a" einen anderen Text? Ignorierst du das alles? Also, in der Ausgabe, nur Zeilen zwischen "ersten" und "zweiten" Auftreten desselben Textes enthalten? – mathguy

+0

Haben Sie jemals zwei AAAAs in benachbarten Reihen? Wenn ja, was machst du? Kann es in der Spalte a andere Werte geben? –

Antwort

0

Annahmen: Die einzigen möglichen Werte in Spalte a sind 'AAAA' und null. Die Anzahl der 'AAAA' Werte kann ungerade sein (in diesem Fall startet die letzte NICHT eine neue Gruppe, sie wird zusammen mit allen null Zeilen davor und danach ignoriert). In der Spalte b gibt es keine doppelten Datumsangaben.

Mit diesen Annahmen: Erstens halten wir eine laufende Anzahl von 'AAAA' Werte, sowie die Gesamtzahl, mit analytischen count() in einer Unterabfrage. Dann passen wir die Gruppennummer (einfach aus der laufenden Zählung berechnet) in der select-Klausel der äußeren Abfrage an und verwenden die laufende Zählung (für null in Spalte a) und die Gesamtanzahl (für 'AAAA' in Spalte a) in where Klausel, um zu bestimmen, welche Zeilen in der Ausgabe beibehalten werden sollen.

Der Code folgt dieser logischen Lösungsbeschreibung sehr genau.

select a, b, ceil(c/2) as grp 
from (
    select a, b, count(a) over (order by b) as c, count(a) over() as max_c 
    from t 
) 
where a is  null and c < max_c and mod(c, 2) = 1 
    or a is not null and c <= 2 * trunc(max_c/2) 
; 

A B    GRP 
---- ---------------- --- 
AAAA 2017/01/01 02:00 1 
    2017/01/01 02:30 1 
AAAA 2017/01/01 03:00 1 
AAAA 2017/01/01 04:30 2 
    2017/01/01 05:00 2 
AAAA 2017/01/01 05:30 2 

Für Spaß und um die Vorteile eines Upgrades auf Oracle 12, ist hier zu zeigen, wie diese, sehr leicht getan werden kann, mit der match_recognize Klausel (hinzugefügt in 12.1):

select a, b, grp 
from t 
match_recognize(
    order by b 
    measures match_number() as grp 
    all rows per match 
    pattern (h x*? h) 
    define h as h.a = 'AAAA' 
); 
+0

Dies half dabei, die Richtung zu geben, die ich benötigte, ich werde daran arbeiten, diese Logik auf meinen Datensatz anzuwenden und zu sehen, ob er funktioniert. Und ja, ich habe schon mal von match_recognize gelesen und warte geduldig auf das 12c Upgrade (wenn wir uns dazu entschließen). – user8914489

+0

@ user8914489 - die 'match_recognize'-Lösung kann dir heute vielleicht nicht helfen, aber wenn ich Antworten posten, tue ich, was ich kann, um anderen Forumsmitgliedern zu helfen (die eine ähnliche Frage haben und bereits Oracle 12 haben). Bitte zögern Sie nicht, weitere Fragen zu beantworten, nachdem Sie Ihre Lösung in Ihrem realen Szenario verwendet haben. – mathguy

Verwandte Themen