Hallo,
ich bin noch relativ unerfahren im Umgang mit SAS und verwende SAS EG 6.1. Ich habe eine Datenbank mit Verträgen. Leider gibt es für jeden aktiven Vertrag für jeden Monatsstand (Format TT/MM/YYYY) einen eigenen Datensatz; wird ein Vertrag gekündigt, so taucht er ab Kündigungsmonat nicht mehr auf. Ich möchte diese Datenbank filtern, so dass ich jeden Vertrag mit dem jeweils jüngsten Monatsstand erhalte (also dem letzten Monat, in dem der Vertrag aktiv war).
In der Excel-Datei habe ich ein Beispiel dargestellt: Die Daten sind bereits nach Verträgen und Datenständen sortiert; Ziel ist, nur die jeweils gelb markierten Datensätze (jüngstes Datum) zu erhalten.
Vielen Dank für die Hilfe
F. Kraus
Hallo FK55,
Du kannst nach dem größten Wert suchen, wenn das Datum nicht als Text sondern als Datum definiert ist:
Data test;
informat DAT_STND anydtdte.;
Format DAT_STND DDMMYYP10.;
informat VNR $8.;
input DAT_STND VNR;
cards;
1/31/2012 44010269
2/29/2012 44010269
3/31/2012 44010269
4/30/2012 44010269
5/31/2012 44010269
6/30/2012 44010269
7/31/2012 44010269
8/31/2012 44010269
9/30/2012 44010269
1/31/2012 44015907
2/29/2012 44015907
3/31/2012 44015907
4/30/2012 44015907
5/31/2012 44015907
run;
Proc sql;
Create table kuend as
select *
from test
group by vnr
having DAT_STND = Max(DAT_STND)
;
quit;
VG
Jan
Bei dem SQL kann man auch die HAVING-Klausel weglassen:
PROC SQL;
CREATE TABLE NEUSTE_VERTRAEGE AS
SELECT VTR
,MAX(DTM) AS DTM FORMAT=DDMMYYP10.
FROM VERTRAEGE
GROUP BY VTR;
QUIT;
Dann wird auch die folgende NOTE vermieden:
NOTE: The query requires remerging summary statistics back with the original data.
Hallo FK55,
ich habe die Einlesedaten stark vereinfacht, aber es ist das selbe Prinzip:
DATA VERTRAEGE;
ATTRIB VTR FORMAT=4.;
ATTRIB DTM FORMAT=DDMMYYP10. INFORMAT=DDMMYY10.;
INPUT VTR DTM;
DATALINES;
2345 01.01.2015
3456 01.01.2015
2345 01.01.2017
2345 01.01.2016
3456 01.01.2016
1234 01.01.2017
;
RUN;
PROC SORT DATA=VERTRAEGE;
BY VTR DESCENDING DTM;
RUN;
DATA NEUSTE_VERTRAEGE;
SET VERTRAEGE;
BY VTR DESCENDING DTM;
IF FIRST.VTR;
RUN;
Viele Grüße
Dennis
erst einmal herzlichen Dank für die schnellen Antworten - ich habe nun versucht, die Selektion in eine Abfrage einzubauen, leider erfolglos. Auch der Weg über einen Stored Process führte nur zu Fehlermeldungen (DAT_STD ist als Datum formatiert):
71 PROC SQL;
72 CREATE TABLE WORK.SORTIERT_VERT_STAND AS
73 SELECT t1.DAT_STND,
74 t1.VNR,
75 t1.PZ_VNR,
76 t1.'AG GEB'n,
Das SAS System
77 t1.AG_BEZ,
78 t1.BSSEU,
79 t1.SALDOIST,
80 t1.RSB,
81 t1.ABDAT,
82 t1.KUENDDAT,
83 t1.ZUTDAT,
84 t1.ZUST,
85 t1.Zustand,
86 t1.TARIF,
87 t1.PRODNR,
88 t1.'Bezeichnung kurz'n,
89 t1.PZSTRUK,
90 t1.PZVERTR,
91 t1.abstruk,
92 t1.ABVERTR,
93 t1.GEBDAT,
94 t1.BERUF,
95 t1.FAMSTD,
96 t1.IHNR,
97 t1.VNR1
98 FROM WORK.FILTER_FOR_BEST_BS_HIST_0001 t1
99 ORDER BY t1.VNR,
100 t1.DAT_STND DESC;
ERROR: Datei WORK.FILTER_FOR_BEST_BS_HIST_0001.DATA existiert nicht.
NOTE: PROC SQL set option NOEXEC and will continue to check the syntax of statements.
101
102 CREATE TABLE NEUSTE_VERTRAEGE AS
103 SELECT t1.VNR
104 ,MAX(t1.DAT_STND) AS t1.DAT_STND FORMAT=DDMMYYP10.
_
22
76
ERROR 22-322: Syntax error, expecting one of the following: eine Zeichenkette in Hochkommata, ',', AS, FORMAT, FROM, INFORMAT, INTO, LABEL, LEN, LENGTH, TRANSCODE.
ERROR 76-322: Syntax error, statement will be ignored.
105 FROM WORK.FILTER_FOR_BEST_BS_HIST_0001 t1
Das SAS System
106 GROUP BY t1.VNR;
107
108 QUIT;
NOTE: The SAS System stopped processing this step because of errors.
NOTE: PROZEDUR SQL used (Total process time):
real time 0.02 seconds
cpu time 0.00 seconds
109 /* --- Ende des Codes für "Filtern und sortieren1". --- */
Viele Grüße
Florian
Beim zweiten SQL schreibst du:
,MAX(t1.DAT_STND) AS t1.DAT_STND
nach dem AS musst du das t1. entfernen:
,MAX(t1.DAT_STND) AS DAT_STND
Der erste SQL sieht soweit richtig aus. Da liegt das wahrscheinlich an der Prozedur davor.
Hallo Florian,
zusätzlich greifst Du auf eine Datei zu, die nicht existiert.
ERROR: Datei WORK.FILTER_FOR_BEST_BS_HIST_0001.DATA existiert nicht.
@Dennis: Dein Einwand, dass das having zu einer Note führt ist richtig. Der Code führt auch in beiden Fällen bei der verwendeten Tabelle zu dem gleichen Ergebnis. Möchte man aber weitere Attribute einer Tabelle haben wird das Ergebnis unterschiedlich sein und es wird die gleiche Note ausgegeben.
Die Note besagt auch nur, dass SAS eine Erweiterung zum SQL-Standard nutzt, dich ich sehr praktisch finde.
Wenn man die Note vermeiden wollte wäre ein adäquater Code z. B:
Proc sql;
Create table kuend as
select T1.*
from FILTER_FOR_BEST_BS_HIST_0001 as T1
, (
select VNR
, Max(DAT_STND) as DAT_STND
from FILTER_FOR_BEST_BS_HIST_0001
group by VNR
) as T2
where T1.VNR = T2.VNR
and T1.DAT_STND = T2.DAT_STND
;
quit;
Man müsste das remerging, dass SAS im ersten Fall selbständig ausführt, explizit programmieren.
Viele Grüße
Jan
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!