Zum Inhalt springen

MySQL aus n Zeilen eine machen (kombinieren)


Raaico

Empfohlene Beiträge

Hallo zusammen ich such mich schon seit Stunden dusslig und dämlich aber finde nichts gescheites.

Ich will(muss) forlgendes hin bekommen.

Erstmal zu meiner Beispielquelle

NR	MENGE	RABATT

101076	5.000	5.00

101077	5.000	5.00

101082	5.000	5.00

101082	15.000	10.00

101083	15.000	10.00

101083	5.000	5.00

101084	5.000	5.00

101084	15.000	10.00

101085	15.000	10.00

101085	5.000	5.00

101086	5.000	5.00

101086	15.000	10.00

101087	15.000	10.00

101087	5.000	5.00
Ich möchte nun das Folgendermaßen haben
NR	MENGE1	RABATT1	MENGEn	RABATTn

101076	5.000	5.00

101077	5.000	5.00

101082	5.000	5.00	15.000	10.00

101083	15.000	10.00	5.000	5.00

101084	5.000	5.00	15.000	10.00

101085	15.000	10.00	5.000	5.00

101086	5.000	5.00	15.000	10.00

101087	15.000	10.00	5.000	5.00
Da wo also die NR gleich ist möchte ich aus n Zeile eine machen und die MENGE und den RABATT hinten anfügen was sich dann dementsprechend vergrößern soll, wenn die NR'n mehrmals vorkommen. ich Hoffe ich habe es verständich ausgedrückt und ihr könnt mir helfen Der absolute Traum wäre nun noch, wenn die Menge dann in der zeile aufsteigend sortiert ist aber ich denke das kann man schon vorher im Select einbauen eh man die zusammenwürfelt. das wäre der befehl womit ich die Obere Tabelle erzeugt habe
SELECT 	RABATT.ARTIKELNR,

	RABATTSTAFFEL.MENGE,

	RABATTSTAFFEL.RABATT

FROM	RABATT


INNER JOIN RABATTSTAFFEL

ON RABATT.RABATTNR = RABATTSTAFFEL.RABATTNR


WHERE	KUNDENNR = 0 AND

	KUNDENGRUPPE = ''


ORDER BY ARTIKELNR

Gruß Raaico

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich werde Dir kein fertiges Statement vorkauen, denn wenn man subselect in Verbindung mit mySQL in eine Suchmaschine eingibt findet man tausende Seite mit Informatione
Stichwort Soziale Kompetenz als Moderator.

Zum eigentlichen Problem:

Ich würde hier eher das Stichwort Pivotieren verwenden. Das ist, sofern die DB hier keinen speziellen Befehl hat nicht ganz so einfach, besonders, da Du evtl. eine unbestimmte Menge an Spalten hast.

Wie man mit Subselects eine unbekannte Menge von Ausprägungen pivotiert würde ich gerne sehen - man lernt ja nie aus.

Sofern hier kein anderer Kollege entsprechende Erfahrung hat (mysql ist nicht unbedingt "meine" DB) und ein "vorgekautes" Beispiel hat, würde sicherlich auch eine Suche in der oben schon genannter Suchmaschine helfen.

Dim

Link zu diesem Kommentar
Auf anderen Seiten teilen

mir würde ja auch gerne das gekochte essen reichen es braucht nicht vorgekaut sein aber bitte auch nicht tief gefrohren^^

genau da sehe ich auch das problem ich weiß nicht ob es in den tausenden daten auch mal vorkommen kann dass zb 5 rabatte hinterlegt sind und somit muss der das irgendwie alleine checken.

ich werde mal nach dem neuen vorgeschlagenen stichwort suchen und hoffe dass ich da mal was gescheites finde um das endlich fertig zu bekommen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

kannst du das stichwort auch näher erklären durch das ganze rumprobiere bin ich voll leer und raff gar nichts mehr

Das Stichwort Subselect, wie Dimitri es schon erwähnt hatte, nutzt dir nichts. Anbei ein Link, welcher dir für MySQL ein Beispiel liefert :

MySQL/Pivot table - Wikibooks, collection of open-content textbooks

(Bin aber auch nicht MYSQL Experte :-))

Gruss

Link zu diesem Kommentar
Auf anderen Seiten teilen

Sorry, ich hab die Indizes nicht gesehen. Ich hatte das so gelesen, dass dort über die Rows mit identischem Schlüssel ein Count gebildet werden soll. Somit wäre es eben durch ein Subselect zu erreichen.

Aber es sollen ja n-Spalten zu n-Datensätzen generiert werden, dann habt ihr recht, es wäre eine Pivot-Tabelle. Aber ich hatte das mal bei mySQL gemacht und finde es durch das Knie, den Kopf in die Brust.

Also ich würde das einfach aus meiner Erfahrung mit mySQL nicht als Pivot bauen, sondern eben ggf durch groups / Stored P. / Views realisieren, so dass eben wieder Row orientiert arbeiten kann. Denn eine Tabelle mit "dynamischer" Spaltenanzahl macht einfach Bauchschmerzen. Vor allem muss die Anwendung dann immer ein select * machen und muss dann entsprechend auch die Felder korrekt verarbeiten.

Oder als Alternative ein anderes DBMS einsetzen, wenn möglich.

Link zu diesem Kommentar
Auf anderen Seiten teilen

also theoretisch könnten es unendlich viele also dynamisch sein aber der Kunde hat mir gerade bestätigt dass es maximal 5 Einträge pro Artikel sind also könnte man das nun schon fest auf 5 staffeln stellen

ich habe da auch schon mal n bissel rum probiert aber ich glaube der kommt nicht so recht mit dem Join der ja noch dazu kommt klar oder ich habe bei meiner syntax was falsch was gut sein kann da ich noch nicht lange mit datenbanken arbeite und am anfang meinr ausbildung zum fachinformatiker stehe und diese aufgabe zum lösen bekommen habe

SELECT	sum(MENGE*(1-abs(sign(MENGE-1)))) as MENGE1,

		sum(RABATT*(1-abs(sign(RABATT-1)))) as RABATT1,

		sum(MENGE*(1-abs(sign(MENGE-2)))) as MENGE2,

		sum(RABATT*(1-abs(sign(RABATT-2)))) as RABATT2,

		sum(MENGE*(1-abs(sign(MENGE-3)))) as MENGE3,

		sum(RABATT*(1-abs(sign(RABATT-3)))) as RABATT3,

		sum(MENGE*(1-abs(sign(MENGE-4)))) as MENGE4,

		sum(RABATT*(1-abs(sign(RABATT-4)))) as RABATT4

FROM	RABATT


INNER JOIN RABATTSTAFFEL

ON RABATT.RABATTNR = RABATTSTAFFEL.RABATTNR


WHERE	KUNDENNR = 0 AND

		KUNDENGRUPPE = ''


GROUP BY ARTIKELNR		

ORDER BY ARTIKELNR

Ich weiß nicht ob sich einige jetzt nach diesem CODE die Haare raufen oder obs gar nicht so falsch ist jedenfalls ist das ergebnis totaler MÜLL Das ergebnis wie gesagt totaler MÜLL
0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	3.000000	0.0000	0.000000	0.0000

0.000000	0.0000	0.000000	0.0000	0.000000	3.0000	0.000000	0.0000

das hatte ich aus dem Beispiel von dbwizard raus genommen und mal angepasst aber wahrscheinlich falsch angepasst

Also es sollen anchher 5 Mengen mit 5 Rabatten da sein und Zellen die nicht gefüllt werden können ruhig NULL sein aber ich komm da nicht weiter wenn da einer ne idee hat wäre das echt genial

Link zu diesem Kommentar
Auf anderen Seiten teilen

ja das ist erfüllt siehe ganz oben mein erster beitrag da ist ja die tabelle im rohzustand also der join davon besser gesagt

denn das sind rabatte die für jeden kunden und jede kundengruppe zählt diese rabatte sollen für listen und so genommen werden als "Werbung" und da sind nur die sinnvoll die für jeden Kunden gelten.

also das ist erfüllt denn die liste von der ausgegangen werden soll ist ja die erste oben und die wurde damit erzeugt

Link zu diesem Kommentar
Auf anderen Seiten teilen

also theoretisch könnten es unendlich viele also dynamisch sein aber der Kunde hat mir gerade bestätigt dass es maximal 5 Einträge pro Artikel sind also könnte man das nun schon fest auf 5 staffeln stellen

Ich würde da evtl dann 6 d'raus machen und alles was evtl > 5 ist, dann in den 6ten hinein werfen. Wenn der == Null ist, dann passt es, wenn nicht, hast Du ein Indiz, dass es eben mehr Rabatte gibt

Zum Code: Ich würde erst mal das Pivot vollständig bauen und als View in die Datenbank einfügen. An diesen View solltest Du dann alle weiteren Informationen anhängen, d.h. Du hast pro Artikel Deine Row und verknüpfst dann diesen Eintrag mit einem Join. Wenn das funktioniert, kommt das nächste. Alles in ein Select so direkt aus dem Kopf zu formulieren ist schwierig. Wenn Du es über Views machst, kannst Du immer stückchenweise das Select erweitern und kannst sicher sein, dass die vorherigen Ausgaben korrekt sind. Wenn dann alles fertig ist, kannst Du das auch dann in einen View zusammenfügen.

Deine Aussage "ist Müll" ist nicht hilfreich, denn Dein SQL Select ist syntaktisch korrekt, sonst würde es kein Ergebnis liefern. Du hast ein semantisches Problem, dafür müsstest Du Daten + Tabellenstrukturen auszugsweise einstellen.

Ich weiß nicht wie Deine Tabellenstrukturen aussehen, aber das Beispiel arbeitet mit Ints, so dass da immer die Summen passend gebildet werden. Wenn Du, wovon ich ausgehe, für Rabat und Menge double / foat hast, dann musst Du ggf Deine Summen anders bilden und ggf mit If und eben Bereichen arbeiten: sum(if value >= 5 and value <=10)...)

Link zu diesem Kommentar
Auf anderen Seiten teilen

also das mit dem "nehme ich mal an" ist zwar logisch auch das man diese datentypen nimmer aber ich bin an diese Datenbank des programms gerichtet und über die logik der datenbank sind oft genug gespräche und naja meist fällt die logik dabei untrn tisch aber das ist ne andere geschichte ich habe mich entschieden es einfacher zu machen jedenfalls die quelle zu vereinfachen

ich habe die Quelltabelle einfach als #tmp gemacht und somit ist die Quelle klar

daann ist es nur noch das problem das richtig einzubringen dass er mir das einzeigt was ich will SIEHE OBEN erster beitrag

CREATE TABLE #tmp(

		Artikelnr varchar(30),

		Menge decimal(15,3),

		Rabatt decimal(5,2))
Dann werden die daten von oben da eingelesen. das wären dann 4016 Zeilen. das hier habe ich bis jetzt als grundform gefunden kann man da was draus machen wenn ja wie? Ich glaube mitlerweile weißt du ja wie ichs haben will^^
SELECT	*

FROM	#tmp

PIVOT

(

  SUM(VaribleValue)

  FOR [Variable] IN ([Sales],[Expenses],[Taxes],[Profit])

)

AS p

Ich finds übrigens echt klasse dass du mir hilfst danke auf jeden fall schonmal

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du willst ja Rabatt 1..n berechnen und wie oft dieser vorkommt, so verstehe ich die Aufgabe.

Ich mach das jetzt mal exemplarisch am Rabatt 1:

Wie ist der denn definiert? Da Du nen decimal hast, muss ja gesagt werden, wenn da der Wert ?? drin steht, ist das Rabatt 1. Das könnte z.B. sein, wenn der Wert zwischen 0 und 5 liegt. Das wäre dann Rabatt 1.

Nun willst Du halt wissen, wie oft in Deinen Daten eben Rabatt 1 drin vorkommt. D.h. Du müsstest so etwas machen "sum(if rabatt > 0 and rabatt < 5 ? 1 ? 0)". Die Datenbank läuft jetzt bei einem Select jeden Datensatz durch und prüft die If Bedinung, wenn sie True ist, dann kommt 1, falls nicht 0 in die Summe. Gedanklich heißt das nun, dass dort wo der Rabatt zwischen 0 und 5 liegt eine 1 gezählt wird, ansonsten 0, d.h. da Du nur 0 oder 1 in der Summe hast. entspricht das nun eben der Anzahl der Zeilen, die den Rabatt in dem Bereich 0 und 5 haben. (rein technisch kann man da auch Ansatt sum andere Funktionen nehmen, eben so wie man es braucht).

Du kannst Dir das auch einfach als For-Schleife über alle Datensätze vorstellen:


rabatte = array[4];


for (over all rows) {

     switch row.rabatt {

        case 0..5     : rabatt[0]++

        case 5..10   : rabatt[1]++

        case 10..15 : rabatt[2]++

        otherwise : rabatt[3]++;

}

if rabatt[3] > 0

   echo "es wurden Rabatte gefunden, die zu viel sind"


for i=0:2

  echo "Rabatt "+(i+1)+ " => "+rabatt[i]

Da Deine Rabattspalte ein decimal ist, kannst Du da nicht einfach mit +-1 dran gehen, denn da kann ja irgendein dezimaler Wert wie z.b. auch 3,1234 stehen. Zu welcher Rabattgruppe würde der gehören? So wie ich das oben in dem Pseudocode habe, würde bei 3,1234 das in das erste case reinfallen, d.h. er würde zu Rabatt 0 (bzw in der Ausgabe 1) gezählt werden.

Du musst Dir als erstes überlegen, wie ist Dein Rabatt n definiert, d.h. woran machst Du in einem Datensatz fest, dass er Rabatt n ist. Das wäre das if in dem Statement.

Link zu diesem Kommentar
Auf anderen Seiten teilen

NEIN ES SOLL NICHTS BERECHNET WERDEN

das ist ja das dumme es soll nur verschoben werden aber wir haben uns jetzt dazu entschlossen dafür ein kleines programm zu schreiben über C# lässt sich das wesentlich leichter umsetzen

denn ich will einfach nur alle Mengen und deren dazugehörigen Rabatte in einer zeile zu der entsprechenden artikelnummer haben wie obens chon beschrieben da gibt es kein chema F das sind nur zufällig gleiche daten

also beispiel ich habe in Spalte NR 2 oder auch 3 mal die gleiche nummer so sollen die rabatte und mengen als menge/rabatt1,2 und 3 hinter der Spalte NR auftauchen und einfach nur aus n (max 5) gleichen einträgen unter NR einer gemacht werden und es sollen dann alle hintereinander aufgereit werden

habs mal als bild beschrieben sollte jetzt anhand dieser random beispielzahlen zu verstehen sein also wenn dir was einfällt bitter gerne SQL befehl ansonsten kein problem mach ichs in C# is halt nur bissel umständlicher dann für den kunden aber damit muss er klar kommen ist nur ein klick merh dann

post-74522-14430448808015_thumb.jpg

Link zu diesem Kommentar
Auf anderen Seiten teilen

Schau Dir das Bild einmal bitte an. Woran identifizierst Du Deinen Rabatt 1 und Deine Menge 1 im Datensatz?

Für mich sieht das so aus, als wolltest das Pivot darin bilden, dass der erste Datensatz immer in die erste Spalte, der zweite in die zweite usw kommt.

So wie mir scheint gehst Du von einer Sortierung der Daten aus. Wenn ich die Ordnung des Sortierschlüssels ändere, dann wäre z.B. auf einmal von Deinem Eintrag 1122 der 1. Rabatt (20,12) und der 2. (5,4)

Geh immer davon aus, dass die Datensätze innerhalb der Tabelle nie so sortiert sind, wie es Dir irgendwelche Tools optisch aufbereiten. Wenn ich den Datensatz 1111 - 2 - 1 nehme, woran weißt Du, dass der Rabatt 1 wird und nicht Rabatt 3? D.h. Du brauchst ein Kriterium für jeden Datensatz, warum dieser genau der eine Rabatt wird. Du muss Dir aus meinem vorherigen Post die "If-Bedingung" überlegen, wobei da natürlich eben der Datentyp des Feldes eine Rolle spielt.

Wie man das dann aufbereitet, sprich was an Information in die Spalte kommt, ist dann der nächste Schritt.

Trotzdem scheint mir das ganze nicht wirklich durchdacht zu sein, denn dass Du hier mit einer Art Sortierung arbeitest, führt oft zu Problemen, wenn man später einfach die Sortierung ändert, dann stimmt der von Dir entwickelte Code nicht mehr.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ergänzung:

Das was die If-Bedingung ist, nennt sich Pivotelement, d.h. Du brauchst "irgendetwas", das Du bildlich in Deinen Datensatz stichst und dann die Tabelle um 90° drehst, so dass eben aus der Zeile eine Spalte wird.

Das Pivotelement muss halt für den Datensatz bekannt sein, Du möchtest im Grunde so etwas wie die Sortierung verwenden, aber wie schon gesagt, das musst Du im Datensatz ablegen. Eine Idee wäre eben ein weiteres Feld in die Tabelle einzufügen z.b. "index", in das Du 1 bis 5 rein schreibst, wenn da eine 1 steht, dann wird es Rabatt 1 usw. (als Alternative könntest Du so etwas auch über den Primärschlüssel des Datensatzes der Tabelle über eine Stored Procedure feststellen lassen, wobei aber dabei zu beachten ist, dass diese Procedure für jeden Datensatz ausgeführt wird und man sich dann das evtl überlegen sollte, wie man diese konzipiert)

So wie Du das aktuell haben willst, fehlt Dir das Pivotelement

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...