mehrere unteranfragen - gelöst -

Hi,

ich bin grade mit einem kleinen verschachtelten Mistding von Query beschäftigt.

Die soll folgendes machen:

tabelle:

name | id | original
teil a | 1 | 0
teil b | 2 | 1
teil c | 3 | 0
teil d | 4 | 1

jetzt sollen bei einer Suche nur die Teile ausgegeben werden, bei denen “original” auf 0 steht, wärs das gewesen würd ich nicht fragen. bei den teilen wo ein original angegeben ist soll aus der gruppe derer mit gleichem original immer das mit der höchsten id aussgegeben werden.

Tja so kanns gehen, während ich das Problem hier schirfitlich formuliert hab ist mir die Lösung eingefallen. Ich sollte das zukünftig immer machen, das aufschribeen und mal gucken ob ich nciht doch eine Lösung finde.

Da ich jetzt soviel getippt hab will ich das dann auch posten, mit Lösung.
Für Anmerkungen dankbar!

Gruß Crypi

SELECT 
			 *
		FROM
			tabelle as a
		WHERE 
			(
				(
					(
						a.original=0
					OR
						a.original is null
					)
			AND
				NOT EXISTS (
						SELECT id 
						FROM 
							tabelle 
						WHERE 
							original=a.id
					   )
				)
			OR
				a.id=
						(
							SELECT max(id) 
							FROM 
								tabelle 
							WHERE 
								original=a.original
						 )
			)
		ORDER BY upper(a.name);

Hallo Crypi,

ist ja 'ne sehr komplizierte Lösung die Dir dazu eingefallen ist. Das Beispiel des Code’s für die Tabelle ist da auch nicht ganz verständlich bzw. ausführlich. Vielleicht hilft dir so was einfaches weiter:

select          *
from            tabelle
where           id in   (
                        select          max (id)
                        from            tabelle
                        where           original = 0
                        group by        upper(name)
                        );

mfg

fristo

hi,

wäre es performance technisch nicht sinnvoller den subselect in den from-teil zu legen? dann würde das nur einmal ausgeführt werden. wenn du ihn in der where-klausel lässt ja bei jeden datensatz…

SELECT tabelle.*
FROM tabelle
, (
SELECT max(id) AS did
FROM tabelle
WHERE original = 0
GROUP BY upper(name)
) AS dummy
WHERE id = dummy.did;

sollte an sich auch gehen und von der performance her besser sein… auch wenn es sich hier nur um einen datensatz handelt sollte man imo immer für größere projekte planen :wink:

cu tb.

ich glaub ich erläutere das beispiel nochmal:

name | id | original
teil a | 1 | 0
teil b | 2 | 1
teil c | 3 | 0
teil d | 4 | 1

ausgegeben werden soll jetzt:
teil c (weil original = 0)
teil d (weil d die höchste id hat, unter den datensätzen die als original 1 haben)

a soll nicht ausgegeben werden, weil es ja datensätze gibt, die a (also id 1) als orginal verwenden.
b soll nicht ausgegeben werden, da d die häöhere id hat, bei gleichem original.

@ fristo mit deinem Beispiel bekomme ich nur die augegeben, wo original auf 0 steht.


gut das ichs doch gepostet hab :slight_smile: [/code]

Hallo Crypi,

nachdem ich gelesen habe, dass Du ein … bist, gebt ich Dir mal eine Hilfestellung.

Analysiere mal den Befehl

select          max (id) 
from            tabelle 
where           original = 0 
group by        upper(name);

und überlege Dir (oder teste es aus), was der Befehl macht.

Nachdem Du den Befehl verstanden hast, wird es Dir nicht schwer fallen den Befehl umzustellen, zudem Du die Randbedingung zum Herausfiltern der 2 Datensätze schon richtig erkannt hast: Original. Aus dem obigen 4 Zeiler wird dann ein 3 Zeiler Einfacher geht es nicht mehr.



mfg

fristo

das ich ein was bin?

zugegeben ich hab bei deinem code jetzt nicht mehr getan als zu kopieren. werd ihn mir nochmal ansehen.

Crypi

Hall Crypi,

das ich ein was bin?

“Beruf: Werksstudent Wirtschaftsinformatik” war gemeint und nichts anderes. Ist das was negatives?


zugegeben ich hab bei deinem code jetzt nicht mehr getan als zu kopieren.

Das hatte ich vermutet.


werd ihn mir nochmal ansehen.

Das wollte ich erreichen. Zum besseren Verständnis der Materie.



mfg

fristo

ok, ging für mich aus deinem post nicht hervor.

Crypi

du kriegst das in drei zeilen hin? ich bin echt beeindruckt… ich mein ich krieg das auch hin nur meine zeilen sind dann sehr, sehr lang :wink:

kannst du mir noch einen tip geben? ich komm da nicht weiter und group by hilft mir wenig, ist eher alles eine verschlimm-besserung…

Danke! Crypi

Hallo Crypi,

An den markierten Stellen ist die Logik nicht eindeutig.


Na ja, ich habe mal nachgedacht und hoffentlich ist es richtig:

DROP TABLE      myTable]

Beide Versionen erbringen das gleiche Ergebnis. Die 2. Version wird wohl schneller sein. Ein Index auf id und original wird höchstwarscheinlich auch noch zur Erhöhung der Geschwindigkeit beitragen.



mfg

fristo

[quote=“fristo”

Das mit der GROUP glaube ich nicht!


An den markierten Stellen ist die Logik nicht eindeutig.

[/quote]

Guten Morgen,

was ich sagen wollte ist, das ich mit Group by nicht weitergekommen bin, nicht das es hier nicht hilfreich wäre.

Das Problem der Logik versteh ich nicht.

Es gibt Datensätze, die id 1 als original verwenden, dass bedeutet, id 1 soll nicht mit ausgegeben werden.
was hier abgebildet werden soll ich quasi ein ein Verlauf, einzelne datensätze werden durch neuere ersätzt, hierbei soll aber nicht verloren gehen, für was die neuen datensätze als ersatz dienen sollen, also wird festgehalten was der ursprungsdatensatz war (original). da immer der aktuellste ausgegeben werden soll muss der mit der höchsten id ausgegeben werden unter denen die das gleiche original haben.


eine sache fehlt bei deinen querys noch, es werden jetzt auch die datensätze die 0 als orignal haben, also datensätze die keinen vorgänger besitzen, gruppiert und immer der mit der höchsten id ausgegeben, dass soll so nicht sein.

nochmal ein besipiel:

name  | id | original
--------+----+----------
 teil a |  1 |        0
 teil b |  2 |        1
 teil c |  3 |        0
 teil d |  4 |        1
 teil e |  5 |        0
 teil f |  6 |        0
 teil g |  7 |        6

gibt bei deinen aus&#58]

- es sollen alle ausgegeben werden, die als original 0 haben und deren id nicht als original verwendet wird (hier c und e)

- es soll jeweils der datensatz mit der höchsten id ausgegeben werden aus einer menge von datensätzen, die das gleiche original besitzen (hier d und g).

funktionieren tut das hier:
[code]
 (select max (id) from myTable 
     where original<>0 group by original) 
UNION 
(SELECT id from mytable as a 
    where a.original=0 
 and 
   not exists 
        (select * from mytable where original=a.id)
);

Hallo Crypi,

ich hatte ja schon beim Nachdenken meine Zweifel Und der einzigste werd’ ich wohl auch nicht gewesen sein, der mit Deiner Beschreibung seine Probleme hatte.

Da muss ich Dir wiedersprechen! Wie Du hier geschrieben hast

ist Deine Analyse gut und Du hast es auch richtig gemacht, das Problem in kleine logische Einheiten zerlegt. Besser geht es nicht mehr. Und der von Dir entwickelte Code

Recht hast Du. Ich hatte ja auch schon mein Zeifel angemeldet. Du solltest aber auch Bedenken: Antworten basieren immer auf den Information die hier schriftlich mitgeteilt werden, und die sind nicht immer vollständig und eindeutig.


Das Aufgabe hast Du also selbst gut gelöst. Es geht doch.



mfg

fristo

ist mir auch nicht leicht gefallen das zu formulieren. naja jetzt ists ja irgendwie geglückt ]
Das Aufgabe hast Du also selbst gut gelöst. Es geht doch.
[/quote]

:slight_smile:

Danke für deine Hilfe!
Crypi