SQL Wie Daten in MySQL speichern?

M

Mr. Snoot

Gast
Hio,

ich habe mehrere Datensätze in meiner DB (Statistik). Jetzt gibt es zu jeder Tabelle/Datenreihe noch Infos (Quelle, Erklärung etc.), die ich ausgeben will (bspw. der Text unter dem Diagramm).

Im Moment ist es erstmal so, dass der Text im PHP-Script steht und via switch-case je nach DB-Tabelle ausgewählt wird, was natürlich doof ist.


Wie könnte ich diesen Zusatztext auch in der DB speichern? Evtl. in eine extra Tabelle welche Felder für Quelle, Erklärung besitzt und das dann auslesen? Aber wie verknüpfe ich das dann am sinnvollsten mit der Datentabelle?
 
wenn ich dich richtig verstanden habe, dürfte folgendes für dich das richtige sein:
du erstellst zu jedem Diagramm einen uniquen numerischen Wert. Soll heißen jedes Diagramm hat ja eine Nummer. Praktisch eine Referenzzahl. In weiteren Tabelle kannst du nun zu jedem dieser Referenzwerte deine zusätzlichen Daten eintragen.

anders werklärt du packst deine Case-Fälle als index in eine Tabelle und liest sie mit WHERE aus.
 
xkynet schrieb:
Soll heißen jedes Diagramm hat ja eine Nummer.
Öhm, nein!? :D

Aber grundsätzlich müsste ich es wie folgt machen?


Aktuell habe für jede Datenreihe eine eigene Tabelle in der Datenbank, eine heißt bspw. cpt.

Jetzt wählt der Besucher eine Datenreihe aus, z.B. eben jene:
PHP:
$statistik = $_POST['cpt']
Dann kommt meine SQL-Abfrage, innerhalb der ich dann auf eine zusätzliche "Quellen"-Tabelle zugreifen, also so in der Art:

PHP:
$sql_daten = "SELECT jahr, daten FROM $statistik"; # Datentabelle
while(...)
{
  $jahr  = ...;
  $daten = ...;

  $sql_infos = "SELECT quelle, erklaerung FROM infos WHERE tabelle = $statistik"; # Infotabelle
  while(...)
  {
    $quelle     = ...;
    $erklaerung = ....;
  }
}
 
edit: dieses Posting hat sich erledigt


Muss man bei der SQL-Abfrage innerhalb einer anderen SQL-Abfrage was beachten? Ich erhalte immer den Fehler:
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource
und die innere Abfrage gibt nichts aus. Ich kann aber keinen Fehler im Quellcode finden.
PHP:
  ...
 
Zuletzt bearbeitet:
Der Benutzer wählt sich die TABELLE aus? Die Tabellen haben Spalten vom gleichen Typ? Ganz schlechte Planung. Das hättest du lieber alles in eine Tabelle hauen sollen und das mit einer zusätlichen ID versehen. Die Spalte "tabelle" der "infos"-Tabelle wäre dann nur noch eine Referenz auf die ID eines Datensatzes der neuen Tabelle mit allen Daten.

Auch dir lege ich den Artikel zur Datenbank-Normalisierung bei Wikipedia ans Herz :)
 
Der Fehler liegt in der MySQL-Abfrage.
Heißt deine Variable $db?

Du hast vergessen, hinter "ODER BY jahr" die Reihenfolge (aufsteigend ASC; absteigend DESC) anzugeben!
Code:
$sql = "SELECT * FROM $db ORDER BY jahr DESC";
 
Was meinst du mit gleicher Typ? Gleiche Feldnamen gibt's jedenfalls nicht.

Der Fehler von eben hat sich jedenfalls irgendwie verflüchtigt :)


@ Eagle-PsyX-: wenn ich nichts angebe wird doch ASC sortiert.
 
@Eagle: Nein, das ist okay so ohne. Der SQL-Standard besagt, dass in dem Fall ASC angenommen wird. Alle mir bekannten DBMS handhaben das auch so.
 
naja, so verkehrt ist das imho nicht. Es sind immerhin eigentlich total verschiedene Quellen, kann ja sein, dass sich da auch mal spalten ändern könnten.
Eine Tabelle der form (jahr, daten, zuwelchertabellegehöricheigentlich) sieht doch was seltsam aus.

@Mr.Snoot
So falsch sieht das eigentlich gar nicht aus. Mach mal noch einfache Quotes ('') um dein $db im zweiten Statement.
Sonst führ es mal in phpmyadmin aus - das hilft auch einiges weiter ;)
 
Ich beziehe mich auf diese Stelle:

PHP:
$statistik = $_POST['cpt'];
$sql_daten = "SELECT jahr, daten FROM $statistik";

Da wird die Tabelle vom Benutzer gewählt. Ich kenne nicht viele Szenarien, wo das so sinnvoll ist. Hier muss ich doch annehmen, dass auch andere Tabellen die Spalten "jahr, daten" haben. Hier wird also auf mehrere Tabellen verteilt, was viel effizienter in einer Tabelle liegen könnte. Meiner Meinung nach ein sehr schlechter Datenbankentwurf.
 
Ich dachte mir es ist übersichtlicher in mehreren Tabellen.

Nicht jede Datenreihe beistzt die Felder jahr und daten, sondern ggf. auch daten1, daten2, geraet1, geraet2 etc.

So habe ich quasi:

Tabelle cpt:
jahr, daten​

Tabelle bpe:
jahr daten1, geraet1, daten2​

Tabelle flops:
jahr, daten1, geraet1, daten2, geraet2​


Nach deiner Lösung - wenn ich es richtig verstehe - hätte ich dann aber:

Tabelle:
jahr, cpt_daten, bpe_daten1, bpe_geraet1, bpe_daten2, flops_daten1, flops_geraet1, flops_daten2, flops_geraet2​


Im Moment habe ich 21 Tabellen, das wäre in einer einzelnen Tabelle doch viel zu unübersichtlich!?
 
Nein, so würde ich das ganz sicher nicht tun, das ist ja noch schrecklicher als die vorherige Lösung :)

Ich wollte dir gerade hier genau hinschreiben, wie ich es tun würde, aber eigentlich ist das keine gute Idee, bevor ich nicht weiß was du in deinen Tabellen wie genau speicherst.

Glaubst du es wäre möglich mir mal Lesezugriff auf die DB zu geben? Ansonsten vielleicht einen SQL-Dump zum selber Rekonstruieren. Ich habe das gute Gefühl, dass deine Probleme durch vernünftige Normalisierung komplett verschwinden.


Nachtrag:

Ich versuche aber schonmal so weit, auch wenn ich nicht verstehe was genau gespeichert wird und wie das aussieht. Wahrscheinlich hast du Redundanzen in deinen Daten.

Mein Vorschlag:

statistik -> {id, typ, beschreibung}
stat_info -> {id_statistik, jahr, nummer, geraet, daten}

Unterstrichen ist Primärschlüssel (ja, die Tabelle "stat_info" hätte in diesem Beispiel einen zusammengesetzten Schlüssel über drei Spalten, und nein, daran ist nichts besonderes! (bevor wieder die Diskussion los geht :) )). Durch Hinzufügen einer zusätzlichen laufenden Nummer zur daten-Tabelle kann man aber auch diese alleine zum Primärschlüssel machen - so wie es da steht ist es aber viel effizienter.

"id" wäre eine automatisch fortlaufende Nummer. "typ" wäre z.B. 'cpt', 'flops' oder sowas. "beschreibung" meinetwegen der Text, der dann im Drop-Down-Menü angezeigt wird (woher auch immer der zur Zeit kommen mag).

"id_statistik" ist ein Fremdschlüssel auf "id". "nummer" ist eben die Geräte- UND Daten-Nummer, die du bei dir über mehrere Spalten verteilt hattest (was nur in Ausnahmefällen eine gute Idee ist. Man macht bei Kunden ja auch nicht "Telefonnummer 1, Telefonnummer 2"... Das ist schlecht zu benutzen und ziemlich ineffizient). In "geraet" und "daten" kommt eben das rein, was bei dir vorher drin stand - was auch immer das sein mag.

Das wäre nun mein Vorschlag. Aber da ich einigermaßen raten musste, was du wie speicherst, sehe das bitte nicht als absolut an :)
 
Zuletzt bearbeitet:
Im Moment sieht es so aus:

db_struktur.jpg

Ich habe also 20 individuelle Datentabellen und zu jeder dieser Tabellen gibts eine Zeile in der Infotabelle.



Was verstehst du denn unter "nummer" ist eben die Geräte- UND Daten-Nummer", meinst du damit dieses daten1, geraet1, daten2, geraet2?

Vielleicht kannst du ja mal mein Bild auf deine Struktur übertragen, im Moment kann ich nicht ganz nachollziehen, wie du das machen würdest. Kann aber natürlich sein, dass du von einer anderen Struktur meinerseits ausgegangen bist und deine aktuelle Variante daher nicht zutrifft.
 
Zuletzt bearbeitet:
@Snoot:

Ja, ich meine damit die "1" und "2", wie du das richtig erkannt hast.

Aber nun fällt mir auf, dass deine "Daten"-Spalten anscheinend alle von unterschiedlichem Typ sind. Im Falle einer gemeinsamen Lösung müsste man sich hier auf einen Datentyp wie double einigen. Ansonsten ist mein Vorschlag erstaunlich nahe an einer guten Lösung für diese Daten.

Nachtrag: Eigentlich würde ich sogar auf die laufende Nummer verzichten und dafür die "geraete" in einer eigenen Tabelle auslagern und statt "nummer" dann einen Verweis auf "id_geraet" verwenden. Ich gehe nämlich davon aus, dass pro Statistik und Jahr kein Gerät zweimal aufgeführt wird. Dann spart man sich diese künstliche "Nummer" und du hast alle Geräte schön sauber in einer Tabelle.


@darkservant:

Die Lösung ist schon ganz alleine dadurch schlecht, weil er nicht Joinen kann. Schon alleine da müsste dir auffallen, dass das Ding unmöglich normalisiert und sinnvoll sein kann. Und dem Benutzer ungefiltert die Tabelle auswählen zu lassen.... Ach, darüber lasse ich mich nun mal nicht aus.

Außerdem wird durch die Abhängigkeit der Spalten "daten1" von "geraet1" (usw.) die dritte Normalform verletzt.
 
Zuletzt bearbeitet:
Hü,

also so ganz versteh ich das Problem, welches ich offensichtlich habe, nicht :)

Ich habe doch jetzt meine Geräte auch alle sauber in einer Tabelle. Wieso auslagern?


weil er nicht Joinen kann
Will ich das - oder sollte ich das wollen? :D


Nach deiner Idee würde es dann so aussehen!?

Code:
stat_info -> {id_statistik, jahr, nummer, geraet, daten}

[B]id_statistik	jahr	nummer	daten	geraet[/B]
[B]1[/B]		1995	1	5.50E+06	Pentium Pro
[B]2[/B]		1997	1	4.50E+06	Pentium MMX
[B]3[/B]		1999	1	2.81E+07	Pentium III
[B]4[/B]		1995	2	1.00E+06	AMD 5x86
[B]5[/B]		1997	2	8.80E+05	AMD K6
[B]6[/B]		1999	2	2.20E+07	AMD K7
Ist das sinnvoller? Und wie sähe es dann aus, wenn ich keine Nummer hätte - dann könnte ich ja gar nicht gezielt auf bestimmte Daten zugreifen.
 
Ja, ich finde das so sinnvoller. Obwohl ich das leicht anders meine:

Code:
stat_info -> {id_statistik, jahr, nummer, geraet, daten}

id_statistik	jahr	nummer	daten	geraet
1		1995	1	5.50E+06	Pentium Pro
1		1997	2	4.50E+06	Pentium MMX
1		1999	3	2.81E+07	Pentium III
2		1995	1	1.00E+06	AMD 5x86
2		1997	2	8.80E+05	AMD K6
2		1999	3	2.20E+07	AMD K7

So in der Art.

Die Nummer ist doch eigentlich nur für die Unterscheidung der Geräte und den zugehörigen Daten untereinander zuständig, oder sehe ich das falsch?

Im Grunde könnte man doch nun die Geräte in eine eigene Tabelle auslagern und anstatt der "nummer" dann auf den Primärschlüssel der Geräte-Tabelle verweisen. Die Daten bekommst du dann durch:

Code:
SELECT a.jahr, a.daten, b.geraet 
FROM daten AS as 
JOIN geraet ON a.geraet_id = b.id 
WHERE a.id_statistik = 1 
ORDER BY jahr
 
Die Nummer ist einfach eine Nummerierung der einzelnen Datenreihen. Statt geraet1, daten1, geraet2, daten2 könnte da auch intel_prozessor, intel_daten, amd_prozessor, amd_daten stehen.

Da ich aber mehrere Tabellen mit mehreren Daten/Geräten habe, wollte ich es vereinheitlichen, damit ich beim Auslesen immer datenX und geraetX habe und mich nicht weiter um die Spaltennamen kümmern muss. Sonst bräuchts ja für jede Tabelle eine andere Abfrage.

Und ob ich jetzt wie bei deiner Variante mit einer ID auf die zweite Tabelle zugreife, oder wie bei mir mit dem Tabellennamen selbst ist doch egal, oder nicht?

Außerdem ist meine Datentabelle insofern übersichtlicher, als dass ich dort jedes Jahr genau einmal mit zugehörigen Daten/Geräten habe. Bei dir hätte ich ja bei 4 Datenreihen auch viermal alle Jahreszahlen. Sollte sich bei dir etwas an einer ID oder einer Jahreszahl ändern, müsste ich dort ja viel mehr Daten ändern, oder nicht?

Deine Idee:
Code:
id	jahr	geraet	daten
1	[COLOR="Red"]19690[/COLOR]	v	100	[COLOR="Green"]// 1969 ist bspw. falsch, muss daher dreimal geändert werden[/COLOR]
1	1971	w	101
1	1972	x	102
1	1973	y	103
1	1974	z	104
2	[COLOR="red"]1969[/COLOR]	a	200
2	1971	b	201
2	1972	c	202
2	1973	d	203
2	1974	e	204
3	[COLOR="red"]1969[/COLOR]	k	300
3	1971	l	301
3	1972	m	302
3	1973	n	303
3	1974	o	304


Meine Variante:
Code:
id	jahr	geraet1	daten1	geraet2	daten2	geraet3	daten3
1	[COLOR="Red"]1969[/COLOR]	v	100	a	200	k	300	[COLOR="Green"]// 1969 ist falsch und muss nur einmal geändert werden[/COLOR]
2	1971	w	101	b	201	l	301
3	1972	x	102	c	202	m	302
4	1973	y	103	d	203	n	303
5	1974	z	104	e	204	o	304


Es kann ja sein, dass deine Variante einen Vorteil hat, aber im Moment sehe ich ihn nicht. Ich habe keine Redundanzen und damit doch auch keine Inkonsistenz o.ä.!?




Wieso verwendest du denn das JOIN? Damit ich nicht zwei DB-Abfragen laufen lassen muss? Ginge das bei meiner Variante nicht?
 
Zuletzt bearbeitet:
Deine Funktionalen Abhängigkeiten
jahr & gerät1 -> daten1
jahr & gerät2 -> daten2
jahr & gerät3 -> daten3

Ein Schlüsselkandidat ist jedoch jahr & gerät1 & gerät2 & gerät3

somit ist die 2. Normalform verletzt.
http://de.wikipedia.org/wiki/Normalisierung_(Datenbank)

(Das Wiederum bedeutet dass dein Schema sehr schlecht ist!)

Das mit dem 3-mal ändern ist übrigends falsch.. das ist ein SQL Befehl, und da auf Jahr hoffentlich ein index ist, ist dieser Befehl auch nicht langsamer.


Kannst du mir mal erklären wo der unterschied zwischen gerät1 / daten1 und gerät2 / daten2 liegt etc. liegt?

Oder erklär einfach mal informell im Detail was für Informationen du in deinen einzelnen Dateien abspeichern willst.
 
Zuletzt bearbeitet:
Zurück
Oben