Array auslesen

- datenbank
- software
Ich habe ein Array wie dieses
$test = array();
$test[0] = array();
$test[0][0] = "1";
$test[0][1] = "abc";
$test[0][2] = "hallo";
$test[0][3] = "morgen";
$test[0][4] = "100";
$test[0][5] = "2025-10-03";
$test[1] = array();
$test[1][0] = "3";
$test[1][1] = "abcd";
$test[1][2] = "hallo22";
$test[1][3] = "morgen";
$test[1][4] = "200";
$test[1][5] = "2025-10-03";
und so weiter
Ich möchte ganz gezielt die indexe [2], [3], [4], [5] der zweiten Ebene auslesen.
Aber nur die, wo zweite Ebene 0 = 3 und zweite Ebene 1 = abcd ist.
Der Index der ersten Ebene ergibt sich aus den Treffern der zweiten Ebene.
Den selben Effekt erreiche ich, wenn ich die erste Ebene mit einer for Schleife durchlaufe und nach [$zähler][0] = 3 AND [$zähler][1] = "abcd" suche. Aber da müsste ich die Schleife für jede Suche nach dieser Kmbi Kombination extra laufen lassen.
Ich brauche quasi so etwas wie eine Datenbankabfrage für eine Array. Geht sowas?
Hallo Mathias,
Performance optimiert man wenn man ein Problem bemerkt oder erwartet. Warum erwartest du eins? Wie oft pro Sekunde wird, über alle Requests hinweg, diese Suche ausgeführt?
Und wie groß ist das Array, das du da durchsuchst?
Rolf
Hi,
Ich habe ein Array wie dieses
Ich brauche quasi so etwas wie eine Datenbankabfrage für eine Array. Geht sowas?
Warum liegen die Daten dann im Array und nicht in einer Datenbank?
cu,
Andreas a/k/a MudGuard
Die Antwort gilt auch für alle anderen, die sich hier sehr ausführlich über meine Frage lustig machen und sich gegenseitig ihre Genialität bestätigen.
Danke!
Mehr kann und will ich dazu nicht sagen, das würde alles nur Sperren nach sich ziehen.
Hi,
Die Antwort gilt auch für alle anderen, die sich hier sehr ausführlich über meine Frage lustig machen
Ich habe mich nicht lustig gemacht.
Das sähe ganz anders aus.
cu,
Andreas a/k/a MudGuard
Lieber Mathias,
sich hier sehr ausführlich über meine Frage lustig machen und sich gegenseitig ihre Genialität bestätigen.
die Relevanz unserer Antworten für gestellte Fragen steht in einem direkten Verhältnis zu der Qualität der Fragestellung. Das betrifft sowohl die Formulierungen, als auch die Struktur davon.
Mehr kann und will ich dazu nicht sagen, das würde alles nur Sperren nach sich ziehen.
Du kannst gerne alles kritisieren, wenn Du eine ehrliche Auseinandersetzung anstrebst. Dann kann man auch offen ansprechen, was in den dich störenden Antworten aufgrund von welchen Dingen in Deiner Fragestellung so geworden ist. Ganz ohne dass Du fürchten müsstest hier gesperrt zu werden! Und in einer solchen Diskussion haben nicht nur wir die Chance, dass wir künftig besser antworten, sondern auch Du, dass Deine Fragen hier künftig treffender gestellt werden. Das wäre in der Tat win-win.
Liebe Grüße
Felix Riesterer
Lieber Mathias,
Ich brauche quasi so etwas wie eine Datenbankabfrage für eine Array.
ist das so? Mir kommt es eher so vor, dass Deine Unter-Arrays in Wirklichkeit Objekte mit Eigenschaften sein möchten. Zumindest kannst Du das einigermaßen nachbilden, indem die Indizes (nicht „Indexe“, bitte!) vernünftige Bezeichner bekommen, anstatt Zahlenwerte:
$test = [
[
'level' => 1,
'name' => 'abc',
'message' => 'hallo',
'availabilitiy' => 'morgen',
'amount' => 100,
'date' => '2025-10-03'
],
[
'level' => 3,
'name' => 'abcd',
'message' => 'hallo22',
'availabilitiy' => 'morgen',
'amount' => 200,
'date' => '2025-10-03'
]
};
Jetzt kannst Du die Indizes level
und name
gezielt auf bestimmte Werte hin untersuchen:
$condition = [
'level' => 3,
'name' => 'abcd'
];
$found = [];
$wanted_properties = [
'message' => 'Nachricht',
'availabilitiy' => 'Verfügbarkeit',
'amount' => 'Menge',
'date' => 'Datum'
];
foreach ($test as $index => $entry) {
$matches = true; // erwarte passenden Eintrag
foreach (array_keys($condition) as $property) {
if ($entry[$property] != $condition[$property]) {
$matches = false;
}
}
if ($matches) {
// In $entry steht ein gesuchter Eintrag von $test: $test[$index]
$wanted_data = [];
foreach (array_keys($wanted_properties) as $property) {
$wanted_data[$property] = $entry[$property];
}
$found[] = $wanted_data;
}
}
Um also zu entscheiden, ob die Arrays in $test
Deinen Kriterien genügen, packst Du diese in ein Beispiel-Array $condition
, um dann dessen Schlüssel-Wert-Paare mit Deinen echten Arrays zu vergleichen. Wenn alles passt, ist die Variable $matches
noch immer true
und Du kannst nun damit anstellen, was Du willst. Hier wird ein neues Array mit genau den Indizes gebaut, die in $wanted_properties
festgelegt werden. Das so neu gebaute Array kommt in eine Trefferliste $found
.
Womit wir beim eigentlichen Thema wären: Was genau willst Du eigentlich(!) erreichen? Deine Problemstellung war eine technische, von der nicht klar ist, ob der Weg dazu überhaupt der beste für Dein Vorhaben ist. Beschreibe also gerne mehr, dann kann man Dir bessere Vorschläge machen!
In meinem Fall sind solche Trefferlisten wie die oben erstellte nicht gut genug. Wenn es um Inhalte geht, die ich aus einer Menge an Daten filtere, will ich immer den originalen Datensatz verfügbar haben. Die oben neu erstellten Arrays sind also genau das, was ich nicht haben möchte. Lieber ist es mir, später z.B. bei der Ausgabe die für die Anzeige notwendigen Eigenschaften (hier Indices) wie im Array $wanted_properties
aus dem ursprünglichen Datensatz zu verwenden:
$found = []; // tun wir so, als ob dort Arrays von $test drin stehen
foreach ($found as $entry) {
foreach ($wanted_properties as $property => $display_name) {
echo $display_name, ': ', $entry[$property];
}
}
Liebe Grüße
Felix Riesterer
Ich brauche quasi so etwas wie eine Datenbankabfrage für eine Array.
Was Dir als "Datenbankabfrage" vorschwebt, ist eigentlich die Nutzung eines Index', den eine Datenbank auf Anforderung anlegt (verwandt, aber nicht zu verwechseln mit dem Index eines Feldes). Ohne so einen Index, einer Art Stichwortverzeichnis, macht auch eine Datenbank lediglich das, was Dir in Form einer for-Schleife momentan Bauchschmerzen bereitet: Sie durchläuft sämtliche Datensätze.
Sprachen (Du hast Deine nicht angegeben) bieten üblicherweise keinen Index über die Daten eines Feldes (array). Unterstützt Deine Sprache assoziative Felder, könntest Du einen Index händisch anlegen:
for i in test:
index[test[i][0] + "\t" + test[i][1]] = i
Das Ergebnis für Dein Beispiel wäre:
$index["1" + "\t" + "abc"] = 0;
$index["3" + "\t" + "abcd"] = 1;
Der Schlüssel besteht in diesem Beispiel aus den Werten 0 und 1 jedes Datensatzes, getrennt durch einen Tabulator (können Deine Werte auch Tabulatoren enthalten, musst Du einen anderen Trenner oder gleich eine Prüfsumme à la md5 oder sha benutzen).
Der dazugehörige Wert ist der Index des Datensatzes in Deinem Feld $test.
Du musst bei jeder Änderung eines Datensatzes auch den Index auf den neuesten Stand bringen (das würde eine Datenbank dir abnehmen). Womit wir dann beim Problem wären:
Du solltest Dir im Klaren sein, dass Du Dir auf diese Weise Fehlerquellen einbaust, die ein vermeintlicher Geschwindigkeitsgewinn nicht wettmachen können wird. Falls Deine bestehende Schleife ohne nennenswerte Verzögerung läuft und Du lediglich um der Bauchschmerzen wegen optimieren möchtest, bist Du wahrscheinlich auf dem falschen Weg.
Finde erst einmal heraus, wie sehr Deine for-Schleife Dein Programm verzögert. Dann überlege Dir, ob Du den Zugriff optimieren müsstest.
Merke: Premature optimization is the root of all evil.
EDIT: Text formatiert — Gunnar
Danke für die Hinweise. Leider haben wir uns da missverstanden. Das Array ist bereits eine Datenbankausgabe. Immer genau eine Zeile. Was ich derzeit mache, ist eine solche Datenbankabfrage mit einer Where Klausel, die mir immer genau einen DS liefert. Das Problem ist, die Datenbank enthält ein paar 100000 Einträge.
Die indizis $test[(zähler)][0] und $test[(zähler)][1] sind eine ein-ein-deutige Kombi in Verbindung mit einem Datum. Der eine Wert ist eine Mitarbeiter ID der andere eine ID aus der VOB. Es gibt zu jedem Mitarbeiter genau alle VOB ID’s zu einem bestimmten Datum. Es gibt ca. 30 Mitarbeiter und 300 VOB-ID’s.
Meine Schleife durchläuft jetzt die Mitarbeiter und gibt zu jedem einen Wert aus den VOB ID’S aus. Da es nun 6000 Kombinationen gibt und der Aufbau in der Statistik pro Mitarbeiter auf der X Achse erfolgt, benötige ich 6000 Datenbankabfragen nach dem jeweils passenden Wert. Ich weiß, lässt sich halt blöd erklären. Natürlich könnte ich nach den VOB ID`s aus der DB auslesen, dort komme ich dann aber mit der extra möglichen unterschiedlichen Anordnung der Mitarbeiter auf der X-Achse in Konflikt. Ich könnte auch alle VOB pro Mitarbeiter auslesen, aber dann müsste ich die HTML-Seite senkrecht aufbauen, was nur durch die nachträgliche Anordnung der DIV Container per CSS möglich ist. Das wird eine so konfuse Rechnerei, das das kein Mensch mehr nachvollziehen kann. Deshalb hatte ich gehofft, es gibt eine Möglichkeit, ein Array wie eine DB abfragen zu können.
Beispiel: Gib mir die indizis 3,4,5,6,7 von dem Eintrag im Array wo der index0 = 1 und index2 = hallo ist. Mittlerweile bin ich nun auch dahinter gekommen, das so etwas nicht möglich ist. Außer ich führe immer wieder eine for-Schleife aus, bis ich zu index 1 und index 2 einen Treffer habe. Aber das findet dann auch 6000 mal statt. Das ist zwar schneller als 6000 DB Zugriffe, aber doch immer noch nicht optimal.
Ich habe jetzt einen neuen Ansatz. Ich werde zuerst die Ausgabe aufbauen ohne Inhalt. Die einzelnen Container enthalten eine Kombi aus index 1 und index 2. Da diese Kombi in der Ausgabe der DB bekannt ist, kann ich diese dann in einer Schleife durchlaufen lassen und jeder Kombi einen Container zuweisen. Diese Zuweisung übergebe ich per Ajax an eine Javascript. Und dort wird dann die Liste der Zuweisungen abgearbeitet. Das bedeutet, die Schleife läuft nur 2x (einmal in PHP und einmal in Javascript) und ich kann jede beliebige Reihenfolge verwenden. Du hast mich mit Deinen zusammengesetzten Indizis darauf gebracht. Danke. Mal sehen, ob es so klappt, wie ich mir das vorstelle.
Hallo,
sorry, aber dein vorhergehender Beitrag ist eine einzige Textwurst ohne jegliche Struktur. Mindestens ein paar Zeilenumbrüche hier und da wären hilfreich, um den Inhalt zu erfassen. So ist es einfach nicht zumutbar.
Einen schönen Tag noch
Martin
@@Der Martin
sorry, aber dein vorhergehender Beitrag ist eine einzige Textwurst ohne jegliche Struktur. Mindestens ein paar Zeilenumbrüche hier und da wären hilfreich, um den Inhalt zu erfassen. So ist es einfach nicht zumutbar.
Das war kein böser Wille. Im Text waren LF oder CR oder beides drin. Aber halt nur einfache. Man braucht bei Markdown aber zwei davon, siehe Hilfe.
Ein anderer Fehler war die Verwendung von `
(was in Markdown – zumindest in der hier verwendeten Variante – die Sonderbedeutung „Inline-Code“ hat) für Apostrophen.
Ich hab beides mal korrigiert. Wobei das Deppenapostrophen sind; da sollten gar keine stehen.
🖖 Live long and prosper
Leider haben wir uns da missverstanden. Das Array ist bereits eine Datenbankausgabe. Immer genau eine Zeile. Was ich derzeit mache, ist eine solche Datenbankabfrage mit einer Where-Klausel, die mir immer genau einen DS liefert.
benötige ich 6000 Datenbankabfragen nach dem jeweils passenden Wert.
Dass du tausende Abfragen benötigst, bezweifle ich jetzt einfach mal. Was du benötigst, ist Hilfe mit SQL.
Ich weiß, lässt sich halt blöd erklären.
Wenn du dein Problem nicht einmal selbst anhand eines abstrakten Beispiels mit vier, fünf Datensätzen (als Eingabe) und dem gewünschten Ergebnis (als Ausgabe) erklären kannst, dann hast du die Aufgabenstellung noch nicht erfasst.
Schleife läuft nur 2x (einmal in PHP und einmal in Javascript)
Du versuchst anscheinend, nicht ausreichende SQL-Kenntnisse mit einem Flickwerk aus PHP und Javascript auszubügeln. Das ist der falsche Weg.
Im Übrigen, wie Martin schon schrieb: Lies' dir deine Texte doch bitte wenigstens einmal durch; was du da jetzt einfach hingeschissen hast –mit Verlaub, anders kann ich das nicht nennen–, ist nicht zumutbar.
Hallo Milch,
das Thema „hingeschissen“ hat Gunnar ja erklärt und repariert. Markdown ist halt auch nur ein weiterer Ölfleck auf der Lernkurve...
Was du benötigst, ist Hilfe mit SQL.
Das scheint mir allerdings so. Ich konnte der Erklärung noch nicht richtig folgen, hatte aber auch den Eindruck, dass das Problem mit geeigneten SQL Mitteln zumindest gemindert werden könnte.
Rolf
@@Rolf B
das Thema „hingeschissen“ hat Gunnar ja erklärt und repariert.
Wobei ich mich kurz gewundert hatte, dass das OP ja ordentlich formatiert war. Hab dann gesehen, dass du da Hand angelegt hast.
Vielleicht sollten wir das nicht einfach stillschweigend tun, sondern die „Delinquenten“ auf die Hilfe verweisen mit der Bitte, beim nächsten Mal ihre Postings selbst anständig zu formatieren.
Markdown ist halt auch nur ein weiterer Ölfleck auf der Lernkurve...
Ja, aber da lohnt es aber, die Lernkurve zu gehen, da Markdown vielerorts eingesetzt wird. Mediawiki-Syntax hingegen …
🖖 Live long and prosper
Hallo Mathias,
ich versuche mal, dein Problem zu strukturieren.
Was ich derzeit mache, ist eine solche Datenbankabfrage mit einer Where Klausel, die mir immer genau einen DS liefert.
Das heißt: Dein Datenbeispiel vom Anfang ist das Ergebnis dieser DB-Abfrage, aber ohne WHERE-Klausel?
Der eine Wert ist eine Mitarbeiter ID der andere eine ID aus der VOB.
Index 0 ist die Mitarbeiter-ID und Index 1 ist die VOB-ID?
Vorschlag 1: Lies die Daten mit fetch_assoc (mysqli) oder der FETCH_ASSOC-Option (PDO), dann sind das keine numerischen Indizes, sondern die Indizes auf Ebene 2 entsprechen den Spaltennamen aus dem SELECT Statement. Wenn Dir die Spaltennamen aus dem SELECT im PHP nicht gefallen, oder wenn Du Spalten in der Query hast, die keinen Namen haben (bei Berechnungen), verwende in der SELECT-Liste die AS Klausel, um eigene Spaltennamen zu vergeben.
Meine Schleife durchläuft jetzt die Mitarbeiter und gibt zu jedem einen Wert aus den VOB-IDs aus. ... (Der) Aufbau in der Statistik (erfolgt) pro Mitarbeiter auf der X Achse
Du erstellst eine Tabelle, mit einer Spalte je Mitarbeiter und eine Zeile pro VOB-ID?
Es gibt zu jedem Mitarbeiter genau alle VOB-IDs zu einem bestimmten Datum. Es gibt ca. 30 Mitarbeiter und 300 VOB-IDs.
Die Tabelle hat demnach ca. 30 Spalten und 300 Zeilen? Plus Zeilen- und Spaltenüberschriften? Und alle ca. 6000 Datenzellen sind gefüllt, es gibt keine unbelegten Datenzellen?
Wie wäre es denn, wenn du der SQL Abfrage ein ORDER BY spendierst? Ich bleibe mal bei deiner Demotabelle und meiner Annahme für Index 0 und 1.
SELECT ma_id, vob_id, col1, col2, col3, col4
FROM xyz_table
WHERE datum = ...
ORDER BY vob_id, ma_id
Ich habe jetzt höchstens Bedenken, dass die Sortierung nicht nach Mitarbeiter-ID, sondern nach Mitarbeiter-Name erfolgen soll. Und dass die VOB-ID ebenfalls nicht das Sortierkriterium ist, sondern dass es zur ID einen Namen gibt, nach dem sortiert werden soll. Für die Mitarbeiter gibt es sicherlich eine Tabelle mitarbeiter(id, name, vorname), wo sie alle drinstehen. Diese Tabelle kann man zum Sortieren heranziehen:
SELECT ma_id, vob_id, col1, col2, col3, col4
FROM xyz_table
JOIN mitarbeiter ON xyz_table.ma_id = mitarbeiter_id
WHERE datum = ...
ORDER BY vob_id, mitarbeiter.name, mitarbeiter.vorname
Disclaimer: in MYSQL kann man meines Wissens nach einer Spalte sortieren, die im SELECT nicht mitgelistet wird. Andere SQL-Server machen das ggf. anders, in dem Fall musst Du mitarbeiter.name und mitarbeiter.vorname im SELECT mit aufführen.
Eine Sortierung nach VOB-Name statt ID kannst Du ähnlich herbeiführen, wenn es eine Tabelle gibt, wo alle VOB-IDs und ihre Namen drinstehen. Ob das erforderlich ist, musst Du selbst wissen.
Unter der Voraussetzung, dass die Tabelle vollständig ausgefüllt wird, bekommst Du jetzt alle Tabellenzellen in zeilenweiser Reihenfolge geliefert. Falls es Lücken gibt, musst Du noch ein bisschen mehr Hirnschmalz reinstecken, darüber diskutieren wir, wenn Du erklärst, dass es Lücken geben kann, d.h. manche Mitarbeiter eben doch nicht alle VOB-IDs haben.
Was Du jetzt noch programmieren musst, ist ein Gruppenwechsel. Die Theorie dazu hat der Dennis vor 9 Jahren im Self-Wiki aufgeschrieben, ob der Artikel den OmA-Test besteht, weiß ich nicht.
Grundsätzlich brauchst Du:
die Initialisierung
Hauptschleife: WHILE ($row)
einen Gruppenvorlauf (pro geschriebener Tabellenzeile)
einen Gruppendurchlauf: WHILE ($vob_id == $row['vob_id'])
<td>...</td>
für diese Zelleeinen Gruppennachlauf
Ende der Hauptschleife
Das ist eine Programmiertechnik aus den 60er Jahren, aber auch heute noch relevant. Vorteil: Du hast nie mehr als eine Row im Speicher, die HTML-Antwort wird sozusagen „durchgestreamt“.
Anders ist es, wenn die Tabelle Lücken hat. In diesem Fall kann es einfacher sein, zunächst alle Rows zu lesen und sie in eine PHP-Tabelle umzukopieren, die passend zur Ausgabe strukturiert ist (Speicher für 6000 DB-Zeilen ist kein Problem, bei 6 Millionen Zeilen wäre das anders, aber die würde ich ohne Paging-Verfahren auch nicht auf eine HTML Seite ausgeben).
Das Umkopieren kostet nicht viel Zeit und kaum zusätzlichen Speicher. Solange ein Array nicht geändert wird, kopiert PHP nur eine Referenz darauf und nicht das ganze Array. Aber, wie gesagt, darüber reden wir wenn es nötig ist, das ist erstmal unnötiger Aufwand.
Rolf
Danke für Deine Ausführungen. Ja, es ist auch ein mySql Problem. Die ganze Anwendung ist aus einer Anforderung heraus entstanden, als dieses Problem noch gar nicht existent war. Die Ausgabe in dieser Form war zu diesem Zeitpunkt überhaupt nicht relevant. Mein Ausgangspunkt ist immer der Mitarbeiter, der eine Liste von VOB zugewiesen bekommt. Eine Zeile der Datenbankausgabe enthält also je eine Liste von VOB zu jedem Mitarbeiter. Die DB Abfrage greift schon auf mehrere Tabellen mit Group By und Order By zu. Die Werte werden dann auch noch mit anderen vergleichen und es gebt Berechnungen dazu. Nur ein mysql Statement ist es halt nicht. Natürlich wäre es sicher möglich, als Hauptindex die VOB zu bekommen und dann zu jeder VOB die Namen. Aber dazu wäre es besser gewesen, die Daten von Anfang an so zu optimieren. Das würde über die Hälfte der DB Zugriffe sparen. Ich muss zugeben, dass mich die Änderung der mySql Abfrage in diese Richtung etwas überfordert. Deswegen bin ich auf die Sache mit dem Array und Ajax gekommen. Ich werde das jetzt erst mal ausprobieren. Danke nochmal.
Hallo Mathias,
ich würde das keinesfalls clientseitig über Ajax machen, die korrekte Datenaufbereitung ist ein Serverthema.
Aber dazu wäre es besser gewesen, die Daten von Anfang an so zu optimieren. Das würde über die Hälfte der DB Zugriffe sparen.
Es ist eine relationale Datenbank. Bei dem von Dir genannten Mengengerüst sollte auch eine „ineffiziente“ Query keine sonderlichen Probleme schaffen (es sei denn, der Server ist eh schon am Dampfen und die Query wird häufig ausgeführt). Es sollte auch kein Problem sein, die Query im Zweifelsfall durch einen zusätzlichen Index zu unterstützen. Bist Du der Alleinentwickler? Oder gibt's Mitarbeiter, z.B. für Serverbetrieb oder DB-Design?
Alternativ zum Gruppenwechsel kannst Du auch die Daten „falsch sortiert“ einlesen und über eine PHP-Tabelle passend machen. Wenn Du z.B. die Daten je Mitarbeiter bekommst, oder nach Mitarbeiter sortiert, dann schreib die Daten spaltenweise in ein Array und lies es für die HTML Ausgabe zeilenweise aus.
Da sind nur 2 Werte in jeder Zelle. Ein Array mit 6000 Einträgen, wobei jeder Eintrag wieder ein Array mit 2 Werten ist (oder ein Objekt mit 2 Eigenschaften), ist für einen Webserver kein Problem.
PHP Arrays müssen auch nicht fortlaufend numerisch indexiert sein. Die Keys können Zahlen sein, die beliebig durcheinander sind, und auch Strings sind möglich. Nutze das, um Suchen zu vermeiden und Dir Array-Indexe zu schaffen, die Direktzugriffe via MA-ID oder VOB-ID ermöglichen.
Allerdings kann ich Dir ohne genaue Kenntnis der Datenbank und der Rahmenbedingungen auch keine detailliertere Hilfestellung geben.
Die ganze Anwendung ist aus einer Anforderung heraus entstanden, als dieses Problem noch gar nicht existent war.
Legacy - die größte Seuche der IT.
Rolf