flash-gordon
Goto Top

MSSQL 2000 / WHERE liefert ein paar Duplikate / Duplikate in Query Ergebnis gleich rauslassen

Der Biber wird sich jetzt wieder an VERENDE festbeissen, aber......

folgendes:


 WHERE ( (VERTRAG.VERENDE IS NULL  OR VERTRAG.VERENDE>= Getdate())

prüft ob ein Vertrag noch läuft, oder ob er ein NULL Wert enthält, dann ist es ein Vertrag ohne Enddatum. Eigentlich sollen beide Arten im Ergebnis erscheinen, aber jedoch nur einmal für eine Person.

Bedingung: wenn eine Person 2 Verträge hat, dann soll der mit dem NULL Wert genommen werden.

Die Personen werden wie folgt abgefragt:

SELECT 

 PGRDAT.ZIMMER as "wic_uid"  

 FROM  L2001.PGRDAT  PGRDAT

Ich hab es mit UNION versucht, indem ich die o.g. Prüfung 2 geteilt hab. Hat aber nicht geklappt. Duplikate waren danach immernoch vorhanden. face-sad

HILFE!

Content-Key: 48016

Url: https://administrator.de/contentid/48016

Printed on: April 26, 2024 at 05:04 o'clock

Member: Biber
Biber Jan 05, 2007 at 14:29:04 (UTC)
Goto Top
Moin flasch-gordon,

nachdem Du ja das Umlaut-Problem selbst in den Griff bekommen hast, würde ich ja gern hier mit an einer Lösung basteln.

Grundsätzlich würde dieses Theater mit diesem VERRECKE/VERENDE-Feld gar nicht so massiv auftreten, wenn Ihr in Eurer DB von vornherein mit einem Dummy-Wert von "31.12.9999" oder ähnlich für "Kein Vertragsende festgelegt" gearbeitet hättet.
Dann ließe sich hier wie auch im letzten Thread ganz einfach mit Max() selektieren.

So bleibt als zweitbeste Variante wirklich nur ein UNION.

Verbal / Pseudo-SQL:

Select ....  from Vertrag, PGRDAT
WHERE ( VERTRAG.VERENDE>= Getdate() AND ...[PGRDAT-VERTRAG-Verknüpfung])
UNION
Select ....  from Vertrag, PGRDAT
WHERE ( (VERTRAG.VERENDE IS NULL  AND ...[PGRDAT-VERTRAG-Verknüpfung]
And PGRDAT.ZIMMER NOT in ( 
   Select PGRDAT.ZIMMER from Vertrag, PGRDAT
   WHERE ( VERTRAG.VERENDE>= Getdate() AND ....)
)
Was hier noch fehlt, sind die zusätzlichen WHERE-Bedingungen, die die VERTRAG und die PGRDAT-Tabelle miteinander verbinden.
Also bitte nicht so abschicken, sonst hast Du mit Sicherheit ein kartesisches Produkt.
Wie hängen die beiden denn zusammen?

Gruß
Biber
P.S. PGRDAT ist auch ein schöner Tabellenname- habt er den Kram 1:1 von dBaseIII migriert? face-wink
Member: flash-gordon
flash-gordon Jan 05, 2007 at 14:48:23 (UTC)
Goto Top
sollte ich dir mal die ganze query zukommen lassen?!

Die DB ist leider bestandteil eines externen Tools, welches ein deutscher Dienstleister über Jahre "weiterentwickelt".

Das das Teil von irgendeiner alten dBase Geschichte stammt, möchte ich gar nicht mal ausschließen.

hier also die ganze bisherige Query, die die Duplikate mit 2 Verträgen ausgibt:

select

 PGRDAT.ZIMMER as "wic_uid",  
 VERTRAG.PNR as "wic_hrid",   
 REPLACE(VER_BAUAZ, '0', '') AS "wic_civility",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.NANAME, 'ö', 'ö'), 'ä','ä'),'ü','ü'),'ß','ß'),'Ö','Ö'),'Ä','Ä'),'Ü','Ü')as "wic_name",  
 REPLACE(VER_BAUAZ, '0', '') AS "wic_name2",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.VORNAME, 'ö', 'ö'), 'ä','ä'),'ü','ü'),'ß','ß'),'Ö','Ö'),'Ä','Ä'),'Ü','Ü')as "wic_firstname",  
 PGRDAT.VOLLHGB as "wic_marital_status",   
 PGRDAT.BETRST as "wic_etablishment",   
 MAKST.KST as "wic_cost_center",  
 CONVERT(varchar(8), MITARBDAT.KONEINTRT, 112) as "wic_rights_beginning",  
 IsNull(CONVERT(varchar(8), VERTRAG.VERENDE, 112), '00000000')  as "wic_rights_end",  
 PGRDAT.ATSTATUS as "wic_manager",   
 PGRDAT.GRUPPE as "wic_hrid_manager",  
 BSTLAND.LND_ISO31662 as "wic_countable_country",  
 REPLACE(VER_BAUAZ, '0', '') AS "wic_number",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.STRASSE, 'ö', 'ö'), 'ä','ä'),'ü','ü'),'ß','ß'),'Ö','Ö'),'Ä','Ä'),'Ü','Ü')as "wic_street",  
 IsNull(PGRDAT.COADR, '')  as "wic_adress_complement",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.ORT, 'ö', 'ö'), 'ä','ä'),'ü','ü'),'ß','ß'),'Ö','Ö'),'Ä','Ä'),'Ü','Ü')as "wic_town",  
 PGRDAT.PLZ as "wic_post_code",   
 REPLACE(VER_BAUAZ, '0', '') AS "wic_province",  
 BSTLAND.LND_ISO31662 as "wic_country"  

 FROM  L2001.PGRDAT  PGRDAT, 
  L2001.VERTRAG  VERTRAG, 
  L2001.MITARBDAT  MITARBDAT, 
  L2001.BST  BST, 
  L2001.LAND  BSTLAND, 
  L2001.MAKST  MAKST
 
 WHERE MITARBDAT.AK = VERTRAG.AK AND MITARBDAT.MAN = VERTRAG.MAN AND MITARBDAT.PNR =  VERTRAG.PNR
 AND PGRDAT.AK = MITARBDAT.AK AND PGRDAT.PNR = MITARBDAT.PNR AND PGRDAT.MAN =  MITARBDAT.MAN
 AND PGRDAT.AK = VERTRAG.AK AND PGRDAT.PNR = VERTRAG.PNR AND PGRDAT.MAN = VERTRAG.MAN
 AND BST.AK = PGRDAT.BSTAK AND BST.BST = PGRDAT.BETRST AND BST.MAN = PGRDAT.BSTMAN
 AND BST.LND = BSTLAND.LND
 AND VERTRAG.AK = MAKST.AK AND VERTRAG.MAN = MAKST.MAN AND VERTRAG.PNR = MAKST.PNR  
 AND VERTRAG.VERTNR = MAKST.VERTNR
 AND PGRDAT.PST_AB  <= Getdate() AND PGRDAT.PST_BIS  >= Getdate()  
 AND VERTRAG.VER_AB  <= Getdate() AND VERTRAG.VER_BIS  >= Getdate()  
 AND MITARBDAT.MA_AB  <= Getdate() AND MITARBDAT.MA_BIS  >= Getdate()  
 AND BST.BST_AB  <= Getdate() AND BST.BST_BIS  >= Getdate()  
 AND MAKST.MK_AB  <= Getdate() AND MAKST.MK_BIS  >= Getdate()  
 AND VERTRAG.VERENDE>= Getdate()
 AND VERTRAG.BESCHSCHL NOT IN ('Kufri25','Kufri')   

UNION

SELECT 


 PGRDAT.ZIMMER as "wic_uid",  
 VERTRAG.PNR as "wic_hrid",   
 REPLACE(VER_BAUAZ, '0', '') AS "wic_civility",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.NANAME, 'ö', '&#x00F6;'), 'ä','&#x00E4;'),'ü','&#x00FC;'),'ß','&#x00DF;'),'Ö','&#x00D6;'),'Ä','&#x00C4;'),'Ü','&#x00DC;')as "wic_name",  
 REPLACE(VER_BAUAZ, '0', '') AS "wic_name2",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.VORNAME, 'ö', '&#x00F6;'), 'ä','&#x00E4;'),'ü','&#x00FC;'),'ß','&#x00DF;'),'Ö','&#x00D6;'),'Ä','&#x00C4;'),'Ü','&#x00DC;')as "wic_firstname",  
 PGRDAT.VOLLHGB as "wic_marital_status",   
 PGRDAT.BETRST as "wic_etablishment",   
 MAKST.KST as "wic_cost_center",  
 CONVERT(varchar(8), MITARBDAT.KONEINTRT, 112) as "wic_rights_beginning",  
 IsNull(CONVERT(varchar(8), VERTRAG.VERENDE, 112), '00000000')  as "wic_rights_end",  
 PGRDAT.ATSTATUS as "wic_manager",   
 PGRDAT.GRUPPE as "wic_hrid_manager",  
 BSTLAND.LND_ISO31662 as "wic_countable_country",  
 REPLACE(VER_BAUAZ, '0', '') AS "wic_number",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.STRASSE, 'ö', '&#x00F6;'), 'ä','&#x00E4;'),'ü','&#x00FC;'),'ß','&#x00DF;'),'Ö','&#x00D6;'),'Ä','&#x00C4;'),'Ü','&#x00DC;')as "wic_street",  
 IsNull(PGRDAT.COADR, '')  as "wic_adress_complement",  
 replace(replace(replace(replace(replace(replace(replace(PGRDAT.ORT, 'ö', '&#x00F6;'), 'ä','&#x00E4;'),'ü','&#x00FC;'),'ß','&#x00DF;'),'Ö','&#x00D6;'),'Ä','&#x00C4;'),'Ü','&#x00DC;')as "wic_town",  
 PGRDAT.PLZ as "wic_post_code",   
 REPLACE(VER_BAUAZ, '0', '') AS "wic_province",  
 BSTLAND.LND_ISO31662 as "wic_country"  

 FROM  L2001.PGRDAT  PGRDAT, 
  L2001.VERTRAG  VERTRAG, 
  L2001.MITARBDAT  MITARBDAT, 
  L2001.BST  BST, 
  L2001.LAND  BSTLAND, 
  L2001.MAKST  MAKST
 
 WHERE MITARBDAT.AK = VERTRAG.AK AND MITARBDAT.MAN = VERTRAG.MAN AND MITARBDAT.PNR =  VERTRAG.PNR
 AND PGRDAT.AK = MITARBDAT.AK AND PGRDAT.PNR = MITARBDAT.PNR AND PGRDAT.MAN =  MITARBDAT.MAN
 AND PGRDAT.AK = VERTRAG.AK AND PGRDAT.PNR = VERTRAG.PNR AND PGRDAT.MAN = VERTRAG.MAN
 AND BST.AK = PGRDAT.BSTAK AND BST.BST = PGRDAT.BETRST AND BST.MAN = PGRDAT.BSTMAN
 AND BST.LND = BSTLAND.LND
 AND VERTRAG.AK = MAKST.AK AND VERTRAG.MAN = MAKST.MAN AND VERTRAG.PNR = MAKST.PNR  
 AND VERTRAG.VERTNR = MAKST.VERTNR
 AND PGRDAT.PST_AB  <= Getdate() AND PGRDAT.PST_BIS  >= Getdate()  
 AND VERTRAG.VER_AB  <= Getdate() AND VERTRAG.VER_BIS  >= Getdate()  
 AND MITARBDAT.MA_AB  <= Getdate() AND MITARBDAT.MA_BIS  >= Getdate()  
 AND BST.BST_AB  <= Getdate() AND BST.BST_BIS  >= Getdate()  
 AND MAKST.MK_AB  <= Getdate() AND MAKST.MK_BIS  >= Getdate()  
 AND VERTRAG.VERENDE IS NULL
 AND VERTRAG.BESCHSCHL NOT IN ('Kufri25','Kufri')   
Member: flash-gordon
flash-gordon Jan 05, 2007 at 18:06:50 (UTC)
Goto Top
ICH HABS.

Dein Ansatz war super. Nur leider war (mein Fehler) der Schlüssel nicht PGRDAT.ZIMMER, sondern VERTRAG.PNR

Demnach:
AND ( (VERTRAG.VERENDE IS NULL  AND
 VERTRAG.PNR NOT in ( 
   Select VERTRAG.PNR from Vertrag, PGRDAT
   WHERE ( VERTRAG.VERENDE>= Getdate()

vielen vielen Dank Biber!
Member: Biber
Biber Jan 05, 2007 at 19:25:35 (UTC)
Goto Top
Umso besser, flash-gordon,

Wenn Du es ausgeknobelt hast.
Bei SQL-Statements sind bei mir oft auch die Grenzen der Abstraktionsfähigkeit erreicht - ganz ohne Probieren alles einfach runterschreiben mach ich da ungern.

Drei Sachen wollte ich noch anregen:

- das Zeitverhalten dieser Abfrage dürfte absolut grottig sein. Ich empfehle Dir nochmal die Prüfung (und ggf. interne Diskussion), ob ihr für diesen Vertrags-Ablauf einen definierten HIGHVALUE-Wert einführen könnt (also ein "Monddatum" 31.12.2099 oder 31.12.9999).
Wenn es die Client-Appz weiß (und genau diesen Wert prüfen und richtig interpretieren kann), dann wäre es SQL-technisch wesentlich einfacher, performanter und wartbarer. Und ob Du ein "offenes Vertragsende" anzeigst als "00000000" oder "99991231"... das ist beides gleich hässlich.

- Plan B: Wenn das nicht geht, weil ihr da noch irgendwelche Lizenzknebeln bis zum Jahr 2023 habt mit dieser DB und da nix Großes ändern dürft, dasn würde ich dieses Statement nicht Clientseitig zusammenschroten und über die Leitung schicken, sondern die Arbeit durch eine kleine Stored Procedure serverseitig abfackeln. Bringt erstens eine Menge Performance und zweitens, so wie diese DB aussieht, ist einer der Grundgedanken von sauberen SQL-Schnittstellen verletzt: jede doofe Client-Application muss bis ins letzte physikalische Detail die Tabellenstrukturen und -relationen kennen. Das kostet nicht nur Performance, sondern auch richtig Geld - weil die ganze Logik clientseitig nachgekaspert bzw. entwickelt werden muss.
Dann lieber ein STP GibMirAlleAktuellenVerträge() mt einem definierten Resultset und gut.

- und wo ich mir ja schon vorhin auf die Lippen gebissen habe.... ääähm... hat diese DB denn auch so etwas wie VIEWs oder gar ein logisches Datenmodell? Solche Statements wie oben sind ja hart der Grenze der Wartbarkeit - ich würde diese ganzen verknibbelten Statements, also beispielsweise alles im ersten SELECT... FROM ....bis UNION als EINEN View definieren.
Dann bleibt vom ganzen Geraffel oben nur noch ein 5-Zeiler übrig:

SELECT * from AlleAktuellenVertraege where VERENDE>= Getdate()
UNION
SELECT * from AlleAktuellenVertraege 
   where VERENDE is NULL 
    and PNR not in (SELECT * from AlleAktuellenVertraege where VERENDE>= Getdate())

Halte ich für wartbarer.

Grüße
Biber
Member: flash-gordon
flash-gordon Jan 05, 2007 at 20:04:29 (UTC)
Goto Top
Hallo Biber,

ich hab mich schon oft über dieses "System" aufgeregt und den Wechsel angestrebt.

Aber mein CFO sieht natürlich nur das bereits investierte Geld und die bislang zuverlässigen Ergebnisse.

ZUm Client. Das Tool wird alle 3 Monate upgedatet und der Client hat mittlerweile 3 MB Festplatenspeicher für sich beansprucht.

Nach der letzten (absolut überflüssigen) Look & Feel Restaurierung der Benutzeroberfläche, ist das ganze aufgrund deiner genannten Gründe und einer Menge schwachsinniger Slide Effekte absolut unproduktiv.

Mal ganz abgesehen von der Performance, die der Server für nur eine DB bereitstellen muss.

Was die Geschichte mit den Views und Procedures angeht: hab ich natürlich so realisiert. Sofern man sich "onsite" befindet liefert der Server das Ergbnis via View in 2 sec.

Da das ganze nachts, scheduliert läuft und direkt ein XML flow in eine remote DB schreibt. Alle i.O.

Ich werde jedoch im nächsten Gespräch mit dem Provider und meinem CFO ein paar deiner Kommentare zur DB Konstruktion mit in die Disko einbringen. face-smile

dank dir nochmal!