![]() |
Array mit DB Ergebnismenge vergleichen
Hallo zusammen,
ich benötige mal einen Denkanstoß: Ich habe ein Array, dessen Inhalt in die WHERE - Clause eines SQL wandert. Danach möchte ich die Ergebnismenge mit dem Ausgangsarry vergleichen. Damit will ich feststellen, welche Werte des Array nicht im Ergebnis des SQL enthalten ist/sind. Beispiel:
Delphi-Quellcode:
Daraus folgt die SQL Abfrage:
a[1] := 'Peter';
a[2] := 'Klaus'; a[3] := 'Paul'; a[4] := 'Theo'; a[5] := 'Bernd';
Code:
Die Ergebnismenge soll mal sein:
SELECT
NAME ,COUNT(*) AS Anz FROM Tabelle WHERE NAME IN ('Peter', 'Klaus', 'Paul', 'Theo', 'Bernd') GROUP BY NAME ORDER BY Anz ASC NAME, Anz Klaus, 10 Bernd, 8 Peter, 5 Theo, 5 Klar ist jetzt: Ich suche 'Paul', weil er in der Ergebnismenge nicht vorhanden ist. So, nun könnte ich Zeile 1 der DB nehmen und mit einer Schleife durch das Array laufen und fragen: Tabelle.Name = a[i] und entsprechend handeln. So, nun könnte ich Zeile 2 der DB nehmen und mit einer Schleife durch das Array laufen und fragen: Tabelle.Name = a[i] und entsprechend handeln. So, nun könnte ich Zeile 3 der DB nehmen und mit einer Schleife durch das Array laufen und fragen: Tabelle.Name = a[i] und entsprechend handeln. Und hier frage ich mich, ob das auch eleganter zu lösen ist oder seht Ihr einen anderen Weg diesen Abgleich durchzuführen? Danke für Tipps! Beste Grüße |
AW: Array mit DB Ergebnismenge vergleichen
Hallo,
verwende statt des Arrays eine TStringList oder TList<string>. Durchlaufe die Ergebnismenge und lösche jeden gefundenen Namen aus der Liste. Was übrig bleibt darfst du behalten. ;-) |
AW: Array mit DB Ergebnismenge vergleichen
In Oracle könnte man das mit Hilfe der Dummy-Tabelle DUAL so lösen:
SQL-Code:
Select * From (
SELECT 'PAUL' as Name, (Select count(*) From Tabelle Where Name='PAUL') as ANZAHL FROM DUAL UNION ALL SELECT 'KLAUS' as Name, (Select count(*) From Tabelle Where Name='KLAUS') as ANZAHL FROM DUAL UNION ALL SELECT 'PETER' as Name, (Select count(*) From Tabelle Where Name='PETER') as ANZAHL FROM DUAL -- usw. ) Where ANZAHL=0 |
AW: Array mit DB Ergebnismenge vergleichen
Hallo Jumpy,
danke, verwende allerdings MS SQL! Hatte mal was mit "HAVING" probiert, geht aber nicht, weil aus der Abfrage ja kein <NULL> Satz hervorgeht, sondern <gar kein> Satz. Hallo Mischerr, das hat was! Ich kann gar nicht nach denen suchen kann, die NICHT da sind, sondern nur die ausschließen, die vorhanden sind! Very cool - Danke. |
AW: Array mit DB Ergebnismenge vergleichen
Die MSSQL-Version wäre dann:
SQL-Code:
Da sollten dann nur die Einträge ohne Namen rauskommen
SELECT 'PAUL' as Name Where (Select count(*) From Tabelle Where Name='PAUL') = 0
UNION SELECT SELECT 'KLAUS' as Name Where (Select count(*) From Tabelle Where Name='KLAUS') = 0 UNION SELECT SELECT 'PETER' as Name Where (Select count(*) From Tabelle Where Name='PETER') = 0 |
AW: Array mit DB Ergebnismenge vergleichen
Hi Jumpy,
ich hatte das mit der "DUAL" Tabelle nicht verstanden. Aber Du hast Recht! In der IBM DB2 (die habe ich gerade im Zugriff) Lösung sieht das dann so aus:
Code:
und bringt die Namen raus, die eigentlich gar nicht vorhanden sind!
SELECT 'PAUL' AS Name FROM sysibm.sysdummy1 WHERE (SELECT COUNT(*) FROM Tabelle WHERE VARI = 'PAUL') = 0
UNION SELECT 'KLAUS' AS Name FROM sysibm.sysdummy1 WHERE (SELECT COUNT(*) FROM Tabelle WHERE VARI = 'KLAUS') = 0 UNION SELECT 'PETER' AS Name FROM sysibm.sysdummy1 WHERE (SELECT COUNT(*) FROM Tabelle WHERE VARI = 'PETER') = 0 Dank und Gruß |
AW: Array mit DB Ergebnismenge vergleichen
Viele DBMS können mit Array-Parametern umgehen und es gibt DB-Zugriffskomponenten, welche das ebenfalls durchreichen können.
SQL-Code:
Leider geht das nicht überall, aber da gibt es auch einen Trick.
SELECT Name, COUNT(*) AS Anz
FROM Tabelle WHERE Name IN :ArrayParameter GROUP BY Name ORDER BY Anz ASC -- SQL.ParamByName('ArrayParameter').ArrayIrgendwas[0] := 'PAUL'; ... -- SQL.ParamByName('ArrayParameter').ArrayIrgendwas := ['PAUL', 'KLAUS', ...]; -- SQL.ParamByName('ArrayParameter').SetArrayIrgendwas(['PAUL', 'KLAUS', ...]); -- oder SonstWie * den ganze SQL-String manuell zusammensetzen * oder Makros und nur diesen einen Teil selber basteln
SQL-Code:
1) Ich hab das bisher vorallem mit Integern gemacht, da ist es extrem einfach über eine ArrayToString-Funktion aus dem Array
SELECT Name, COUNT(*) AS Anz
FROM Tabelle WHERE Name IN (&ArrayMacro) GROUP BY Name ORDER BY Anz ASC -- SQL.MacroByName('ArrayMacro').Value := 'a,b,c'; // siehe (1)
Delphi-Quellcode:
einen
[1,2,3]
Delphi-Quellcode:
String zu generieren, ohne auf das Quoting achten zu müssen.
'1,2,3'
Für Strings sollte man hier "unbedingt" die Quote-Funktion der DB-Zugriffskomponenten verwenden und damit den String erzeugen. also sowas wie ![]() bzw. quote_name, quote_value, ![]()
Delphi-Quellcode:
'''PAUL'', ''KLAUS'', ...'
Delphi-Quellcode:
S := '';
for i := 0 to High(DeinArray) do begin if S <> '' then S := S + ', '; S := S + DBQuoteValueFunction(DeinArray[i]); end; PS: ![]()
SQL-Code:
--SELECT n
--FROM (VALUES ('Peter'), ('Klaus'), ('Paul'), ('Theo'), ('Bernd')) AS t(n) --LEFT JOIN tabelle ON name = n --WHERE ... weiß ich grade nix ... halt irgendwas mit count()=0 oder so SELECT n FROM (VALUES ('Peter'), ('Klaus'), ('Paul'), ('Theo'), ('Bernd')) AS t(n) WHERE not exists(SELECT * FROM tabelle WHERE upper(name) = upper(n)) |
AW: Array mit DB Ergebnismenge vergleichen
Also die Idee mit der Tabelle Dual von Oracle finde ich gut.
Da ich aber überwiegend mit FireBird arbeite, lege ich mir dort in jeder Datenbank die Tabelle Dual an und schon kann ich alles so lösen, wie ich es von Oracle gewohnt bin. (Und brauche mir bei der Portierung von DB-System A nach DB-System B keinen Kopp machen, ob die SQLs unverändert übernommen werden können oder nicht ;-)) Was spricht dagegen, diese Lösung auch bei anderen Datenbanken einzusetzen?
SQL-Code:
(Mehr ist Dual unter Oracle auch nicht ;-))
create table dual(dummy char(1));
insert into dual (dummy) values ('X'); commit; |
AW: Array mit DB Ergebnismenge vergleichen
Bei MSSQL sollte auch folgendes Statement alle Namen auflisten, die nicht im obigen SELECT vorkommen
SQL-Code:
SELECT A.Name
FROM (VALUES ('Peter'), ('Klaus'), ('Paul'), ('Theo'), ('Bernd')) AS A(Name) LEFT JOIN Tabelle B ON (A.Name= B.Name) WHERE (B.Name IS NULL) |
AW: Array mit DB Ergebnismenge vergleichen
@Delphi.Narium: Warum keine Temp-Table? (am Besten nur für diese Session)
Ich war davon ausgegangen, dass es mehrere Nutzer mit dem Namen "Bernd" geben könnte, also auch mehrere Datensätze, aber im Printip geht es dann auch wie bei Uwe Raabe, aber vielleicht noch mit einem DISTINCT usw. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz