Datumsexistenz ermitteln

IchHH

Datenbank-Guru
Beiträge
284
Hallo liebe SQL-Freunde,

ich habe gerade aktuelles Problem und komme einfach nicht auf eine vernünftige Lösung.

Wenn ich für jeden Artikel verschiedene Datumsbereiche habe in den diese Verfügbar waren wie z.B.

01.11.2010-28.02.2015
01.03.2015-31.07.2015
01.02.2016-01.01.2510

ich aber nur wissen möchte welcher Artikel mit den jeweils unterschiedlichen Datumsbereichen am 01.01.2015 nicht vorhanden war aber vor 2015 vorhanden waren.

Ich hoffe ich habe das verständlich ausgedrückt. Ansonsten fragen mich wenn Ihr Fragen habt.

Ich danke euch aber schon jetzt für die Hilfe.
 
Werbung:
eine Idee mit PostgreSQL. Wird nich 1:1 übernehmbar sein, aber vielleicht erkennst den Weg ...

Code:
test=*# select * from ichhh ;
 artikel |         bereich         
---------+-------------------------
       1 | [2010-11-01,2015-02-28)
       1 | [2015-03-01,2015-07-31)
       1 | [2016-02-01,2017-07-31)
       2 | [2016-02-01,2017-07-31)
       3 | [2010-02-01,2012-07-31)
(5 rows)

test=*# with not_2015_01_01 as (select distinct artikel from ichhh except select distinct artikel from ichhh where bereich @> '2015-01-01'::date) select * from ichhh where artikel in (select * from not_2015_01_01) and lower(bereich) < '2015-01-01' ;
 artikel |         bereich         
---------+-------------------------
       3 | [2010-02-01,2012-07-31)
(1 row)

test=*#
 
Aaaahhhhh jaaaaa!

Habe nichts verstanden aber dennoch eine Frage.
Kann ich in "Bereich" auch zwei Spalte eingeben von jeweils das Von-Datum und das Bis-Datum enthalten ist?
 
ja, sicher, ist halt nur mehr zu vergleichen. Ich verwende da DATERANGE und kann da recht effektiv mit arbeiten, aber das kann auch nur PostgreSQL.
 
Ja großartig. Vielen Dank.

Nun der Aufruf an die MSSQL Kollegen wie bekomme ich die Abfrage mit den zwei Spalten von und bis hin?
Wie geht ich mit den '::' um und wie wende ich den Subquery in meiner Abfrage an.

Ich habe den Code aktuell für SQL wie folgt angepasst:
Code:
With not_2015_01_01 as (select distinct [2016].[sa110ds_kvnr] from S_6148_1 except select distinct artikel from S_6148_1 where [S_6148_1].[vz_versich_beginn]> '2015-01-01')
select * from S_6148 where [2016].[sa110ds_kvnr] in (select * from not_2015_01_01) and lower([S_6148_1].[vz_versich_beginn]) < '2015-01-01'

Ich hätte nun meine normale Selectanfrage darunter gesetzt und nur die Spalte not_2015_01_01 hinzugefügt, richtig?
 
Sorry der "With Code" läuft in MSSQL komplett anders und ich stehe wieder komplett auf den Schlauch.
Mein Code auf den die oben genannte Regel angewendet werden soll sieht wie folgt aus:
Code:
Select [2015].[sa110ds_kvnr] As [sa110ds_kvnr_2015]
,    [2015].[sa110ds_Verstage_gesamt] As [sa110ds_Verstage_gesamt_2015]
,    [2016].[sa110ds_kvnr] As [sa110ds_kvnr_2016]
,    [2016].[sa110ds_Verstage_gesamt] As [sa110ds_Verstage_gesamt_2016]
,    Sum([2016].[sa110ds_Verstage_gesamt] - [2015].[sa110ds_Verstage_gesamt]) As [Differenz]
,    [S_6148_1].[vz_versich_beginn]
,    [S_6148_1].[vz_gesperrt] As [vz_gesperrt1]
,    [S_6148_1].[v_gesperrt] As [v_gesperrt2]
,    not_2015_01_01
From     [dbo].[S_6148] As [S_6148_1]
Inner Join    (Select *
From     [dbo].[S_6430] As [S_6430_1]
Where    Cast([S_6430_1].[sa110kopf_Berichtsjahr] As [VARCHAR]) Like '2016') As [2016]
On    [2016].[v_kvnr_pers] = [S_6148_1].[v_kvnr_pers]
Inner Join    (Select *
From     [dbo].[S_6430] As [S_6430_1]
Where    [S_6430_1].[sa110kopf_Auswertungsart] = 2
And    Cast([S_6430_1].[sa110kopf_Berichtsjahr] As [VARCHAR]) Like '2015') As [2015]
On    [2016].[sa110ds_kvnr] = [2015].[sa110ds_kvnr]
Group By    [2015].[sa110ds_kvnr]
,    [2015].[sa110ds_Verstage_gesamt]
,    [2016].[sa110ds_kvnr]
,    [2016].[sa110ds_Verstage_gesamt]
,    [S_6148_1].[vz_versich_beginn]
,    [S_6148_1].[vz_gesperrt]
,    [S_6148_1].[v_gesperrt] Having Sum([2016].[sa110ds_Verstage_gesamt] - [2015].[sa110ds_Verstage_gesamt]) > 1

Nur bekomme ich das mit den With Einbau hier überhaupt nicht hin. Ich bitte DRINGEND um Hilfe.

Vielen Dank.
 
Also dein DB Design ist schonmal kompletter Irrsinn daher fasse ich da nichts an und fange schon gar nicht an Code umzubauen aber grundsätzlich sehe ich das mit ganz einfachen Mitteln erstellt, auch ohne WITH.
Code:
SELECT   DISTINCT t1.ArtikelID
FROM   tabelle t1
WHERE NOT EXISTS (
SELECT   1
FROM   tabelle t2
WHERE   t1.ArtikelID = t2.ArtikelID
AND       '2015-01-01' BETWEEN t2.von AND t2.bis )
oder vieleicht auch
Code:
SELECT   t1.ArtikelID
FROM   tabelle t1
GROUP BY t1.ArtikelID
HAVING sum(CASE WHEN '2015-01-01' BETWEEN t1.von AND t1.bis THEN 1 ELSE 0 END) = 0
 
Code:
test=# create table ichhh_2 as select artikel, lower(bereich), upper(bereich) from ichhh ;
SELECT 5
test=*# select * from ichhh_2 where artikel in (select distinct artikel from ichhh_2 except select artikel from ichhh_2 where  '2015-01-01'::date between lower and upper) and upper < '2015-01-01';
 artikel |   lower    |   upper   
---------+------------+------------
       3 | 2010-02-01 | 2012-07-31
(1 row)

mal als Schnellschuß, bitte vorsichtig und gründlich prüfen ...
 
Ok das man an meine Abfrage nicht ran möchte, muss ich akzeptieren aber nicht verstehen. Ich habe nun den Code mal genommen und versucht umzuarbeiten. Das Ergebnis ist NULL ohne Fehlermeldung.

Code:
SELECT DISTINCT t1.v_kvnr_pers, max(t1.[vz_versich_beginn]) as [vz_versich_beginn], t1.[vz_versich_ende]
FROM   S_6148 t1
WHERE NOT EXISTS (
SELECT   1
FROM   S_6148 t2
WHERE   t1.v_kvnr_pers = t2.v_kvnr_pers
AND       '2015-01-01' BETWEEN t2.[vz_versich_beginn] AND t2.[vz_versich_ende])
Group by t1.v_kvnr_pers, t1.[vz_versich_ende]


für mich würde sich nun auch die Frage stellen wenn ich solche Datumsfelder habe
upload_2018-9-19_14-15-35.png
und er mit eigentlich die erste Spalte ausgeben müsste da sichergestellt ist das 2015 ein Datensatz vorhanden war (Beginn) und am 01.01.2015 nicht vorhanden war, wo prüft der Code die Existens auf eine Zeit in 2015?
 
Letzteres dürfte daran liegen das ich eine Bedingung vergessen habe. Vor dem Stichtag soll es ja mal einen Vertrag gegeben haben also würde ich sagen
Code:
SELECT DISTINCT t1.v_kvnr_pers, max(t1.[vz_versich_beginn]) as [vz_versich_beginn], t1.[vz_versich_ende]
FROM   S_6148 t1
WHERE t1.[vz_versich_beginn] < '2015-01-01'
AND NOT EXISTS (
SELECT   1
FROM   S_6148 t2
WHERE   t1.v_kvnr_pers = t2.v_kvnr_pers
AND '2015-01-01' BETWEEN t2.[vz_versich_beginn] AND t2.[vz_versich_ende])
Group by t1.v_kvnr_pers, t1.[vz_versich_ende]
ist schon näher dran. Warum das jetzt NULL liefert ist mir nicht klar.
 
Hallo,

dass funktioniert auch auch. Wenn man eine Spalte mit "Datum von" und eine Spalte mit "Datum bis" sowie eine Spalte mit "Kundennummer" und "Datum beginn" hat, dann muss es doch möglich sein zu prüfen ob ein Kunde am 01.01.2015 kein Eintrag hat?! (Dieser müsste dann ausgegeben werden) Anschließend müsste dann nur noch geprüft werden, ob das Datum im "Datum beginn" kleiner ist als 01.01.2015.

Wenn das System die Datumsbereiche kennen würde hätte man sogar nur sagen müssen
Beginn > '01.01.2015'
Ende < '01.01.2015'
 
Wenn ich das richtig verstehe ist dein Problem ja nicht mit den 3 Werten zu arbeiten (Datum von, Datum bis, Stichtag) und die Bedingung zu prüfen sondern das es mehrere Datensätze mit Zeiträumen zum selben Kunden geben kann.

NOT EXISTS ist grundsätzlich dafür erstmal ein probates Mittel. Du nimmst eine Liste aller Kunden und filterst im WHERE-Teil mit NOT EXISTS alle Kunden, die einen Vertrag haben wo dein Stichtag (01.01.2015) innerhalb des Zeitraums von / bis liegt. Alle diese Kunden haben ja einen Vertrag zum Stichtag gehabt.
 
Werbung:
Wenn ich das richtig verstehe ist dein Problem ja nicht mit den 3 Werten zu arbeiten (Datum von, Datum bis, Stichtag) und die Bedingung zu prüfen sondern das es mehrere Datensätze mit Zeiträumen zum selben Kunden geben kann.

NOT EXISTS ist grundsätzlich dafür erstmal ein probates Mittel. Du nimmst eine Liste aller Kunden und filterst im WHERE-Teil mit NOT EXISTS alle Kunden, die einen Vertrag haben wo dein Stichtag (01.01.2015) innerhalb des Zeitraums von / bis liegt. Alle diese Kunden haben ja einen Vertrag zum Stichtag gehabt.
Ja das ist weit richtig. Aber genau da stellt sich für mich die Fragen, wie ich den 01.01.2015 filtern soll wenn nur Von-Bis Bereiche vorhanden sind. Den die Datumsbereiche Ende sehr sehr selten zum 31.12. und fangen am 01.01. wieder an.

Ohne den Code wirklich zu kennen müsste die Where-Bedingung dann wie folgt aussehen.

Where '01.01.2015' NOT EXISTS between Datum_von and Datum_bis
and Year(Vertrag_beginn) < 2015
and Vers_Begin > '01.01.2015'

Nur wie würde der Code dann aussehen?
 
Zurück
Oben