e51bomag
Goto Top

Hilfe bei Datenbankabfrage

Hallo liebe Community,

hab gerade ein Blackout bzgl. Realisierung einer Abfrage.
Folgende Datenbank:

noten: nid, loginname, fid, note, type
(type = 0/1, halbjahr oder endjahr)

klassen: kid, bezeichnung

faecher: fid, bezeichnung

faecherklassen: fkid, kid, fid


Was ich nun will, eine Abfrage welche mir alle Noten für eine Klasse ausliefert, mit der Struktur:
- Fach1, Fach2, Fach3...
Loginname1 Note Note Note
Loginname2 Note Note Note
Loginname3 Note Note Note

Wird dann in einem C# DataGridview dargestellt.

SELECT faecher.bezeichnung, noten.note, noten.loginname FROM klassen INNER JOIN faecherklassen ON klassen.kid = faecherklassen.kid INNER JOIN faecher ON faecherklassen.fid = faecher.fid INNER JOIN noten ON faecher.fid = noten.fid WHERE klassen.kid = (SELECT klassen.kid FROM klassen WHERE klassen.bezeichnung = 'Temp') AND noten.type = 0

Das war mein 1. Gedanke, aber das haut ja überhaupt nicht wirklich hin.

Content-Key: 281641

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

Ausgedruckt am: 19.03.2024 um 10:03 Uhr

Mitglied: michi1983
michi1983 31.08.2015 um 15:49:52 Uhr
Goto Top
Hallo,

und der Lehrer hat euch nicht erklärt wie man das macht?

Gruß
Mitglied: ukulele-7
ukulele-7 31.08.2015 um 16:18:56 Uhr
Goto Top
Welche Datenbank wäre gut zu wissen.

Du hast mehrere Möglichkeiten:
a) Mehrere, statische Joins, einen für jedes Fach (leicht in der Umsetzung, viel Code, bei neuen Fächern muss angepasst werden)
b) Pivot, abhängig von der Datenbank
c) Rekurisve Abfragen, abhängig von der Datenbank
d) Verkettung der Inhalte (glaube nicht das das in deinem Sinne ist) GROUP_CONCAT (MySQL), XML PATH (MS SQL)
...
Mitglied: e51bomag
e51bomag 01.09.2015 um 08:07:51 Uhr
Goto Top
@michi1983:
Ich bin dabei eine "kleine" Software zu programmieren in Eigenregie, also nix mit Lehrer ;)

@ukulele-7:
Es handelt sich um eine MYSQL-Datenbank
Mitglied: ukulele-7
Lösung ukulele-7 01.09.2015, aktualisiert am 23.09.2015 um 11:59:03 Uhr
Goto Top
Hier ein Beispiel:
SELECT	n0.loginname,
		n1.note AS Note_Fach1,
		n2.note AS Note_Fach2,
		n3.note AS Note_Fach3
FROM	(	SELECT	DISTINCT loginname
			FROM	note ) n0
LEFT JOIN noten n1
ON		n0.loginname = n1.loginname
AND		n1.fid = (	SELECT	fid
					FROM	faecher
					WHERE	bezeichnung = 'Fach1' )  
LEFT JOIN noten n2
ON		n0.loginname = n2.loginname
AND		n2.fid = (	SELECT	fid
					FROM	faecher
					WHERE	bezeichnung = 'Fach2' )  
LEFT JOIN noten n3
ON		n0.loginname = n3.loginname
AND		n3.fid = (	SELECT	fid
					FROM	faecher
					WHERE	bezeichnung = 'Fach3' )  
Es empfiehlt sich natürlich die Fächer IDs statisch einzutragen. Die Lösung erfordert für jedes Fach einen Join.
Mitglied: e51bomag
e51bomag 02.09.2015 um 09:12:46 Uhr
Goto Top
Die Lösung sieht erstmal gut aus. Und gibt es nun die Möglichkeit die Fächer dynamisch abzufragen?
Da für verschiedene Klassen verschiedene Fächer vorhanden sind und diese sich jährlich ändern könnten.
So etwas wie eine Foreach - Schleife in MySQL vielleicht?
Mitglied: ukulele-7
ukulele-7 02.09.2015 aktualisiert um 09:22:03 Uhr
Goto Top
Ich bin in MySQL nicht so fit und es gibt einige Einschränkungen gegenüber z.B. MSSQL mit dem ich viel mache. Aber du müsstest auf jedenfall in der Lage sein mit einer Schleife das Statement zusammenzubauen, also für jedes Fach einen Join zu erzeugen, und dann mit EXEC() auszuführen. Ich weiß aber auch nicht wie Performant das wird wenn man sagen 50 oder 100 Joins führt.
Mitglied: e51bomag
e51bomag 23.09.2015 um 11:59:46 Uhr
Goto Top
So, falls jemand ein ähnliches Problem hat, hier die Lösung in C#
string query = "SELECT n0.loginname AS Benutzername";  
            int i = 1;
            while (i - 1<faecher.Length)
            {
                query += ", n" + i +  ".note AS " + faecher[i - 1];  
                i++;
            }
            query += " FROM (SELECT DISTINCT loginname FROM noten) n0 ";  
            i = 1;
            while (i - 1 < faecher.Length)
            {
                query += "LEFT JOIN noten n" + i + " ";  
                query += "ON n0.loginname = n" + i + ".loginname ";  
                query += "AND n" + i + ".fid = ( SELECT fid ";  
                query += "FROM faecher ";  
                query += "WHERE bezeichnung = '" + faecher[i - 1] + "' ) ";  
                i++;
            }
Mitglied: e51bomag
e51bomag 28.09.2015 um 13:34:11 Uhr
Goto Top
Nun ist mir eben aufgefallen, das noch die Einschränkung für nur eine Klasse fehlt. Wie kann man das jetzt in diesem Fall geschickt einbauen?
Mitglied: ukulele-7
ukulele-7 28.09.2015 um 13:41:36 Uhr
Goto Top
Was genau meinst du? Es fehlt ein Datensatz oder eine Bedingung?
Mitglied: e51bomag
e51bomag 28.09.2015 um 15:34:21 Uhr
Goto Top
Es müsste noch die Bedingung fehlen, das es nur schüler bzw deren noten von einer bestimmten klasse anzeigt.
Weiß jetzt nicht an welcher oder welchen stellen die bedingung überall hin muss.
Mitglied: ukulele-7
ukulele-7 29.09.2015 um 07:43:22 Uhr
Goto Top
Also bei SELECT DISTINCT loginname FROM note könntest du mit einem WHERE eingrenzen, welche Schüler angezeigt werden sollen. Das ginge auch mit einem Join, diese Abfrage muss einfach nur die richtigen Schüler zurück geben und zu allem was an Schülern raus kommt werden alle Noten gejoint. Wenn du nur bestimmte Noten willst, musst du überhaupt erst weniger Joins machen, das muss in diesem Fall deine Schleife besorgen. Ich würde sagen bei
14. query += "AND n" + i + ".fid = ( SELECT fid ";
15. query += "FROM faecher ";
könnte man noch ein WHERE faecher IN oder NOT IN einbauen.