MS SQL - Abfrage, Hilfe
Tannenbaum
- datenbank
0 Marian0 Vinzenz Mai0 Marian0 Vinzenz Mai0 Marian
0 Ilja-1 Tannenbaum-1 fanelf.de0 Vinzenz Mai0 Klaus Mock0 fanelf.de
Hallo,
ich brauche eure Hilfe, und zwar:
Ich habe 2 Datenbanktabellen und es gibt keine Primärschlüssel o.ä.:
1. Tabelle
_____________________________________________________________________
Kennziffer Name
1 Bauer
2 Schmidt
3 Schumacher
2. Tabelle
_____________________________________________________________________
Kennziffer Von Bis Tage
1 01.01.2005 00:10:00 02.02.2005 00:30:01 4
2 04.01.2005 00:35:00 06.02.2005 00:20:00 24
1 05.01.2005 00:30:00 07.02.2005 00:30:00 3
1 04.01.2005 00:30:00 12.02.2005 00:40:00 45
3 07.01.2005 00:35:00 22.02.2005 00:30:06 66
1 08.01.2005 00:38:00 21.02.2005 00:20:00 23
3 08.01.2005 00:30:00 06.02.2005 00:12:08 45
Ich brauche eine Abfrage, die folgendes liefert:
Die Namen einzeln, also 1x "Bauer", 1x "Schmidt", 1x "Schumacher" und nicht 4x "Bauer", 1x "Schmidt" und 2x "Schumacher".
Den größten Eintrag "Von", also max(Von), und die dazugehörige "Bis" und "Tage".
Das muss dann so aussehen:
Name Von Bis Tage
Bauer 08.01.2005 00:38:00 21.02.2005 00:20:00 23
Schmidt 04.01.2005 00:35:00 06.02.2005 00:20:00 24
Schumacher 08.01.2005 00:30:00 06.02.2005 00:12:08 45
Danke schon mal!
Hi Tannenbaum,
Das muss dann so aussehen:
Name Von Bis Tage
Bauer 08.01.2005 00:38:00 21.02.2005 00:20:00 23
Schmidt 04.01.2005 00:35:00 06.02.2005 00:20:00 24
Schumacher 08.01.2005 00:30:00 06.02.2005 00:12:08 45
Ich denke mal du musst erst alle max(Von) raussuchen und dann in ein zweites SELECT einbauen, wo du dann die anderen Sachen dazu raussuchst (mit einem JOIN auf tabelle1.name)
Es könnte vielleicht auch irgendwie in einem SELECT gehen irgendwie indem du irgendwie das max(von) jeder person raussuchst und die Tabelle2 mit sich selbst joinst oder so... Keine Ahnung, ganz so gut kenn ich mich mit MySQL nicht aus.
Gruß, Marian
Hallo
Das muss dann so aussehen:
Name Von Bis Tage
Bauer 08.01.2005 00:38:00 21.02.2005 00:20:00 23
Schmidt 04.01.2005 00:35:00 06.02.2005 00:20:00 24
Schumacher 08.01.2005 00:30:00 06.02.2005 00:12:08 45Ich denke mal du musst erst alle max(Von) raussuchen und dann in ein zweites SELECT einbauen, wo du dann die anderen Sachen dazu raussuchst (mit einem JOIN auf tabelle1.name)
Iljas Lösungsvorschlag aus dem verlinkten Archivthread sollte auch hier anwendbar sein.
Keine Ahnung, ganz so gut kenn ich mich mit MySQL nicht aus.
Das ist nicht schlimm, schliesslich geht es hier nicht um MySQL, was von Vorteil ist. Denn der MS SQL Server unterstützt Subselects, bei MySQL müsste es schon Version 4.1 oder größer sein.
Freundliche Grüße
Vinzenz
Hi Vinzenz Mai,
Iljas Lösungsvorschlag aus dem verlinkten Archivthread sollte auch hier anwendbar sein.
https://forum.selfhtml.org/?t=119749&m=768457
Keine Ahnung, ganz so gut kenn ich mich mit MySQL nicht aus.
Das ist nicht schlimm, schliesslich geht es hier nicht um MySQL, was von Vorteil ist. Denn der MS SQL Server unterstützt Subselects, bei MySQL müsste es schon Version 4.1 oder größer sein.
Hab ich gar nicht gesehen! Aber es gibt jetzt schon MySQL5 - da sollte man dann wenigstens so langsam mal Version 4 haben.
Außerdem: so wenig Micro$oft wie möglich ;~)
Gruß, Marian
Hallo Marian,
bei MySQL müsste es schon Version 4.1 oder größer sein.
Hab ich gar nicht gesehen! Aber es gibt jetzt schon MySQL5 - da sollte man dann wenigstens so langsam mal Version 4 haben.
wie bereits im ersten Abschnitt erwähnt, reicht eine Version 4.0.x nicht aus, es muss 4.1.x sein.
4.0.15 ist noch im Einsatz. Es soll auch Hoster geben, die aus Lizenzgründen noch die Version 3.23.18 im Einsatz haben.
Freundliche Grüße
Vinzenz
Hi Vinzenz Mai,
bei MySQL müsste es schon Version 4.1 oder größer sein.
Hab ich gar nicht gesehen! Aber es gibt jetzt schon MySQL5 - da sollte man dann wenigstens so langsam mal Version 4 haben.
wie bereits im ersten Abschnitt erwähnt, reicht eine Version 4.0.x nicht aus, es muss 4.1.x sein.
Mein ich ja. Tippfehler.
Gruß, Marian
yo,
wie Vinzenz schon richtig anmerkte, sollte auch hier eine korrelierende unterabfrage zum gewünschten ergebnis führen.
SELECT t1.kennziffer, t1.name, t2.von, t2.bis, t2.tage
FROM tabelle1 AS t1, tabelle2 AS t2
WHERE t1.kennziffer = t2.kennziffer
AND t2.von = (SELECT MAX(t3.von) FROM tabelle2 AS t3 WHERE t2.kennziffer = t3.kennziffer)
anzumerken ist dabei, dass bei datensätzen mit den gleichen max datums-wert auch mehrere ergebnisse pro person aufgelistet werden.
Ilja
SELECT t1.kennziffer, t1.name, t2.von, t2.bis, t2.tage
FROM tabelle1 AS t1, tabelle2 AS t2
WHERE t1.kennziffer = t2.kennziffer
AND t2.von = (SELECT MAX(t3.von) FROM tabelle2 AS t3 WHERE t2.kennziffer = t3.kennziffer)
Alles klar. Ich mach das so, da es doch keine doppelten "max(Von)" vorkommen sollen. Danke ;)
Habe immer noch keine Lösung :(
Hallo
Habe immer noch keine Lösung :(
Warum nicht? Es wurde eine funktionierende Lösung vorgeschlagen, die Du nur an Dein Problem anzupassen brauchst. MS SQL-Server hat jedenfalls keine Probleme mit Subselects.
Was hast Du versucht, woran bist Du gescheitert?
Freundliche Grüße
Vinzenz
Was hast Du versucht, woran bist Du gescheitert?
Ich kriege zwar Datensätze mit Name + max(Von) + Bis + Tage, aber wenn gleiche Einträge bei Bis oder Tage enthalten sind, werden die Datensätze mehrfach angezeigt.
z.B.
max(von)
Bauer 08.01.2005 00:38:00 21.02.2005 00:20:00 23
Bauer 08.01.2005 00:38:00 22.02.2005 00:20:00 23
Bauer 08.01.2005 00:38:00 22.02.2005 00:20:00 40
Hallo
Was hast Du versucht, woran bist Du gescheitert?
Ich kriege zwar Datensätze mit Name + max(Von) + Bis + Tage, aber wenn gleiche Einträge bei Bis oder Tage enthalten sind, werden die Datensätze mehrfach angezeigt.
z.B.max(von)
Bauer 08.01.2005 00:38:00 21.02.2005 00:20:00 23
Bauer 08.01.2005 00:38:00 22.02.2005 00:20:00 23
Bauer 08.01.2005 00:38:00 22.02.2005 00:20:00 40
Ja, das hatte Ilja bereits erwähnt, dass dieses Ergebnis zu erwarten ist. Für diesen Fall benötigst Du ein weiteres Kriterium, das den von Dir gewünschten Datensatz ermittelt. Dieses Kriterium kannst Du genauso einbauen wie das erste.
Freundliche Grüße
Vinzenz
Hi,
ja, so wie Ilja die Abfrage formuliert hat ist das verständlich.
Vielleicht sollte man keine Unterabfrage in der Where-Klausel verwenden,
sondern eine Parallel-Abfrage, die bereits nach Kennziffer gruppiert.
Ich habe mal die Tabellen in Users und Actity umbenannt ... damit es
anschaulicher wird.
SELECT A.Kennziffer,
C.Name,
A.Von,
A.Bis,
A.Tage
FROM Activity AS A,
(SELECT D.Kennziffer,
Max(Von) AS max_von
FROM Activity D
GROUP BY D.Kennziffer) AS B,
Users AS C
WHERE A.Kennziffer = B.Kennziffer
AND A.Von = B.max_von
AND C.Kennziffer = A.Kennziffer
ORDER BY A.Kennziffer
Alternativ wäre in Erwägung zu ziehen, für die Tabelle Activity einen
Primärschlüssel einzuführen um so einen einzelnen Eintrag sehr schnell
und effektiv bei der Hand zu haben.
Ciao, Frank
PS: Vielen Dank für die Mittagspausenablenkung ;)
du mußt die 'vielen ergebniszeilen' aggregieren.
SELECT t1.Name, MAX(t2.Von), t2.Bis, t2.Tage
FROM tabelle1 t1 JOIN tabelle2 t2 USING(Kennziffer)
GROUP BY t1.Name, t2.Bis, t2.Tage
ORDER BY t1.Name ASC
sollte ausreichen
Hallo fanelf,
SELECT t1.Name, MAX(t2.Von), t2.Bis, t2.Tage
FROM tabelle1 t1 JOIN tabelle2 t2 USING(Kennziffer)
GROUP BY t1.Name, t2.Bis, t2.Tage
ORDER BY t1.Name ASC
nein, Iljas Lösung ist richtig :-)
Deine Lösung würde wieder zu mehreren Einträgen je Name führen, was laut Ausgangsposting nicht gewünscht ist.
Die Aufgabenstellung lautet:
Gib mir aus Tabelle 1 den "Namen",
aus Tabelle 2 die Spalten "Von", "Bis" und "Tage",
aber zu jeder "Kennziffer" nur die Zeile mit dem höchsten Wert in der Spalte "Tage". Genau dies liefert der Vorschlag von Ilja, wobei Ilja korrekt hinzugefügt hat, dass es im Falle von doppelten Max-Werten auch wiederum zu doppelten Einträgen kommen kann.
SELECT
t1.name,
t2.von,
t2.bis,
t2.tage
FROM tabelle1 AS t1
INNER JOIN tabelle2 AS t2
ON t1.kennziffer = t2.kennziffer
WHERE t2.von = (
SELECT MAX(t3.von) FROM tabelle2 AS t3 -- kann bei Gleichheit zu
WHERE t2.kennziffer = t3.kennziffer -- Mehrfacheinträgen führen
)
Das einzige Problem stellt die Anpassung dieses Statements an die tatsächlich vorhandenen Tabellennamen und ggf. Spaltennamen dar.
Freundliche Grüße
Vinzenz
Hallo,
Genau dies liefert der Vorschlag von Ilja, wobei Ilja korrekt hinzugefügt hat, dass es im Falle von doppelten Max-Werten auch wiederum zu doppelten Einträgen kommen kann.
sollte der Fall eintreten (können) dass es zueiner Kennziffer mehrere Datensätze gibt, welche den gleichen Wert in der Spalte 'von' aufweisen, so werden eben mehrere Datensätze geliefert. Falls das unerwünscht ist, so ist die Aufgabenstellung definitiv unterspezifiziert.
Grüße
Klaus
hallo vinzenz,
du hast recht.
die problemstellung des fragestellers läßt sich mit 'sauberem' sql nicht als einfacher select lösen, da das gewünschte ergebnis einen mix aus gruppierten und ungruppierten spalten darstellt. daher ergibt sich die von ilja genannte lösung, welche zunächst gruppiert die relevanten zeilen ermittelt, und diese dann als bedingung für einen ungruppierten select darstellt.
das problem entsteht aber nicht durch 'doppelte' max-werte, da max selbst bei doppelten werten immer nur einen max-wert liefert.
die 'doppelten' zeilen entstehen durch die 'saubere' notation. dies ist die aggregation von 'Bis' und 'Tage'.
eine ausnahme bildet mysql. es ist in dieser hinsicht sehr tolerant und erlaubt die selektion weiterer spalten, ohne diese zu aggregieren. bei verzicht auf die aggregation von 'Bis' und 'Tage', werden diese als 'nicht aggregiert' geliefert. somit wäre das gewünschte ergebnis erreicht.
yo,
eine ausnahme bildet mysql. es ist in dieser hinsicht sehr tolerant und erlaubt die selektion weiterer spalten, ohne diese zu aggregieren. bei verzicht auf die aggregation von 'Bis' und 'Tage', werden diese als 'nicht aggregiert' geliefert. somit wäre das gewünschte ergebnis erreicht.
ein irrglaube, dass mysql toleranter wäre. dies wird deutlich, wenn man sich mal die dokumentation durchlesen würde. mysql erzeugt halt nur kein fehlermeldung, wo eine angebracht wäre. und es würde alles andere als das gewünschte ergebnis erreicht.
Ilja
probiers aus. dann siehst es.
toleranz ist auch, die fehler eines anderen nicht anzumeckern.
yo,
probiers aus. dann siehst es.
ich gebe dir mal den link, damit du es nachlesen kannst, dass mysql nicht toleranter ist, sondern es nur aus performance-gründen so regelt.
http://dev.mysql.com/doc/refman/5.1/en/group-by-hidden-fields.html
dazu das entscheidene zitat: "Do not use this feature if the columns you omit from the GROUP BY part are not unique in the group! You get unpredictable results."
toleranz ist auch, die fehler eines anderen nicht anzumeckern.
aha, und ich denke, wer genug selbstvertauen hat, der ist auch tolerant genug, fehler oder angebliche fehler von sich selbst zuzulassen.
Ilja