stefanlausl
Goto Top

MSSQL 2014 Problem bei Vollständigkeitsprüfung

Hallo,

ich habe drei Tabellen mit folgenden Spalten:

Tabelle1: [Id] ,[Laufendenummer]

Tabelle2: [Id_Tabelle1], [Anzahl Seiten]

Tabelle3: [AngelegtAm], [Paginiernummer]


Jeder Eintrag in Tabelle 1 ist ein Multitif mit genau so vielen Seiten wie in Tabelle2 gespeichert sind
Zu jeder Seite erhalten ich eine Paginiernummer in Tabelle3.

Meine Aufgabe soll es sein sicherzustellen das alle Datensätze die in Tabelle1 enthalten sind die richtige Menge an Datensätze in Tabelle3 haben und umgekehrt.

Sind keine Lücken vorhanden sehen die Tabelle wie folgt aus (Annahme 1 Multitif mit 4 Seiten also 2 Blätter Vorderseiten mit A Rückseiten mit B)

Tabelle 1: Id , [LaufendeNummer]
1 , 12234546[1] --> die 1 entspricht dem Teil der Paginiernummer aus Tabelle 3 welche als Erstes eingelesen wurde
2 , 12234546[3] --> nächstes Multitif

Tabelle 2: [Id_Tabelle1], [Anzahl Seiten]
1 , 4
2 , 6

Tabelle 3: [AngelegtAm], [Paginiernummer]
01.01.2016 ,12234546[1A]
dito ,12234546[1B]
dito ,12234546[2A]
dito ,12234546[2B]

Die LaufendeNummer erhöht sich also nur alle 2 Einträge,
2 Einträge bedeuten jeweils das Vorhandensein von A und B
Insofern muss das Ergebnis der Abfrage lauten das der Eintrag 1 aus Tabelle 1 mit 4 Seiten vollständig in Tabelle 3 vorhanden ist.

Meine Idee war nun das Vorhandensein der 4 Einträge für Id 1 in Tabelle 1 zu "simulieren".
D.h. Ich selektiere die LaufendeNummer aus Tabelle1 und dessen Seitenanzahl.
Danach ergänze ich die LaufendeNummer mit A und B und addieren das nach jeder geraden Seite die LaufendeNummer.
Die Selektion per [LEFT JOIN] würde mich dann zum Ergebnis führen
Quasi :

12234546
([1] + 0) + A (Seite1 Vorderseite)
([1] + 0) + B (Seite1 Rückseite)
([1] + 1) + A (Seite2 Vorderseite)
([1] + 1) + B (Seite2 Rückseite)

Leider habe ich keine Ahnung wie ich das per SQL lösen kann.
Evtl. habt Ihr eine Antwort für mich.
Sofern jemand die Problemstellung verstanden hat. face-smile

Vielen Dank schon mal im Voraus

Content-ID: 325330

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

Ausgedruckt am: 16.11.2024 um 11:11 Uhr

StefanLausL
StefanLausL 03.01.2017 um 15:08:19 Uhr
Goto Top
OK.
So könnte es gehen.


WITH c10(num)
AS
(
SELECT 0 num UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
),
c10000(num)
AS
(
SELECT c1.num + (c2.num * 10) + (c3.num * 100) + (c4.num * 1000) num
FROM c10 c1,c10 c2,c10 c3,c10 c4
),
Seiten
AS
(
SELECT c.num,t.Seite
FROM c10000 c
CROSS JOIN
(SELECT 'A' Seite UNION ALL SELECT 'B' Seite)t


)


SELECT RTRIM(b.LaufendeNummer + (s.num % 2)) + s.Seite,
*
FROM
Seiten s
JOIN
Tabelle2 di
ON
di.Id_Tabelle1 = 1
AND
s.num < di.AnzahlSeiten / 2
JOIN
Tabelle1 b
ON
di.Id_Tabelle1 = b.Id
ORDER BY b.LaufendeNummer
Dirmhirn
Dirmhirn 03.01.2017 um 15:22:03 Uhr
Goto Top
Hi,

ist das eine vorhandene DB die du überprüfen sollst? ist das eine Aufgabe für die Schule? Ist das eine neues System und die Abfrage soll eine "Funktion" bieten?

sonst wäre es sicher hilfreich wenn du dein Beispiel noch etwas schöner ausführst.

Code-Blöcke zb...

sg Dirm
StefanLausL
StefanLausL 03.01.2017 um 15:28:23 Uhr
Goto Top
Der Abgleich ist für eine vorhandene DB deren Struktur und Aufbau ich nicht beeinflussen kann.
Der Abgleich muss täglich laufen.
Es dürfen keine Datensätze fehlen.

Sorry, ich wüsste nicht was ich noch ausführen soll.
Es gibt noch keine Code Blöcke o.ä.
StefanLausL
StefanLausL 03.01.2017 um 15:31:59 Uhr
Goto Top
Ein Fehler hat sich noch eingeschlichen.
Es muss lauten:

RTRIM(b.LaufendeNummer + s.num ) + s.Seite


Es geht nun auch mit 60 Seitigen Dokumenten.

Danke hat sich erledigt
Dirmhirn
Dirmhirn 03.01.2017 um 17:43:26 Uhr
Goto Top
Du kannst hier im Forum Zeilen als Code formatieren. Lässt sich dann einfach besser lesen. Oder wenn du von einer laufenden Nummer sprichst und immer die selbe einfügst. Datum kann man auch schnell mal kopieren...
Super, dass du es selbst lösen konntest. Fürs nächste Mal halt.
Biber
Biber 03.01.2017 um 19:33:25 Uhr
Goto Top
Moin StefanLausL,

möglicherweise kannst du diese Dummy-Hilfstabelle etwas einfacher erzeugen.

Meine (ungetestete) Idee wäre in etwa
WITH seite AS (
  SELECT 1 as lfdseite, '1A' as PaginierNr    
  UNION ALL
  SELECT lfdseite+1, Rtrim(Trunc( (lfdseite+2)/2, 0)) + case when right(paginiernr, 1) = 'A' then 'B' else 'A' end   
  
  FROM seite 
  WHERE lfdseite < 1000 
)
SELECT * FROM seite
Da sollte auch eine Tabelle mit einer LfdSeite (also fortlaufende Seitennummer) rausfallen und die "Übersetzung" in eine Paginiernummer.

Den eigentlichen Vergleich über einen Join usw. kannst du so machen wie oben.
Mir scheint allerdings, dass es hier
AND s.num < di.AnzahlSeiten / 2
... statt kleiner wohl kleinergleich sein sollte?

Ich habe in der Skizze auch auf saubere Typkonvertierung verzichtet... wenn der MSSQL-Server bei dir nicht gemeckert hat beim impliziten Casten mit RTRIM(b.LaufendeNummer + (s.num % 2)) + s.Seite, dann wird er mir auch verzeihen.

Brutal, was MS da alles erlaubt... wie sollen die Kidz jemals SQL lernen dabei?

Grüße
Biber
StefanLausL
StefanLausL 04.01.2017 um 08:26:12 Uhr
Goto Top
Moing Biber,

Ja das schaut einfacher aus als mein CTE.

Leider habe ich wohl doch auf diesem Server nur MSSQL 2012.

Insofern wird die Funktion TRUNC() nicht erkannt.
Das wäre ja nicht so schlimm, aber die Rekusionstiefe beträgt leider nur 100 statt Deinen 1000.
Das ist für mich leider nicht ausreichend.
Weiterhin musste ich bei meinem CTE mit der Zahl 0 beginnen um die laufende Nummer hochzuzählen.

Insofern würde das dann so aussehen:


WITH seite AS (
  SELECT 0 as lfdseite, CAST('0A' AS NVARCHAR(100)) AS PaginierNr   
  UNION ALL
  SELECT lfdseite+1, CAST(RTRIM((lfdseite+1)/2) + CASE WHEN RIGHT(RTRIM(paginiernr), 1) = 'A' then 'B' else 'A' end AS NVARCHAR(100))   
  FROM seite 
  WHERE lfdseite < 100
)
SELECT * FROM seite

Dies ist aufgrund der fehlenden Rekursionstiefe für mich leider unbrauchbar.
Biber
Biber 04.01.2017 um 14:23:42 Uhr
Goto Top
Moin StefanLausL,

da hätte ich noch einen Tipp.
Die voreingestellte Rekursionstiefe ist 100, die maximale Rekursionstiefe ist 32767.

Du musst einfach nur als neue letzte Zeile ergänzen:
OPTION (MAXRECURSION 4711)

Also in der CTE-Skizze
With seite as ( 
...
)
Select from seite
OPTION (MAXRECURSION 4711) 

Statt 4711 natürlich einen Wert, der dir angemessen erscheint.

Grüße
Biber
StefanLausL
StefanLausL 04.01.2017 um 14:26:03 Uhr
Goto Top
Super Danke !!