PHP & MySQL

querytail

Erfahrenes Mitglied
Hallo zusammen,

ich habe mal wieder eine Herausforderung, denn ich benötige eine Abfrage, die mehrere Zeilen aus einer Tabelle in eine Ausgabenzeile packt. Dabei muss die Zeile eine feste Spaltenanzahl haben:

Bsp:
Tabelle: priceforarticle
Code:
ID			|	ARTID		|	ABS	| PERC	|	AMOUNT	| AMOUNTTO
__________________________________________________________________
7fbfca1af7	|	123456781	|	0	|	3	|	4		| 9
a34b258b03	| 	123456782	|	0	|	5	|	10		| 19
400c7e7d40	| 	123456781	|	0	|	5	|	10		| 19
8d2036a872	| 	123456784	|	0	|	5	|	10		| 19
400c333340	| 	123456781	|	0	|	10	|	20		| 99

Wenn ich z.B. folgende Abfrage nehme:
Code:
SELECT artid, GROUP_CONCAT(abs,perc,amount,amountto ORDER BY perc ASC SEPARATOR '-') AS abs FROM priceforarticle WHERE artid = '123456781' GROUP BY artid

wird mir folgendes angezeigt:

Code:
 0349-051019-0102099

Nun muss ich aber Einzelwerte (einzelne Spalten) haben. die wie folgt aussehen sollen:
Code:
123456781 | 	3 (%)	|	4-9 (Pc)	|  5 (%) | 10-19 (Pc)	|	10 (%)	| 20-99 (Pc). 
123456784 |		5 (%)	|	10-19 (Pc)	| 		 | 				|			|	|
Der jeweils kleinste Werte (%) soll links stehen und wenn eine Spalte leer ist, soll sie leer dargestellt werden.

Ich hoffe, dass das jemand versteht. Daraus wird eine CSV.

Grüße & Danke

querytail
 
3 Fragen mal vorab:
- Warum ist Artid 123456782 nicht im lezten Codeabschnitt? Gibt es noch irgendwelche Filter von denen wir nichts wissen?
- "Dabei muss die Zeile eine feste Spaltenanzahl haben". Und die wäre? In deinem Beispiel kommt Artid 123456781 3 mal vor und die anderen beiden 1 mal. Heisst das also jede Artid kommt maximal 3 mal vor (1-3)? Oder gilt 1-n?
- Im letzten Codeabschnitt hast du (%) und (Pc). Soll da also alles varchar sein? Und sind die Zahlen in der ersten Tabelle auch tatsächlich vom Typ number?
 
Hallo und danke für die Antwort,

123456782 müsste auch noch in die Liste. Sorry, habe ich vergessen. Es gibt keinen Filter.
Ja genau, 3x artid ist Maximum (zur Zeit).
% und Pc (Stück) sind nur Zusatz und müssen nicht unbedingt in die Spalten geschrieben werden. Wenn möglich, dann als varchar.

Die ersten beiden Spalten sind vom Typ: char.

Viele Grüße

querytail
 
ich habe jetzt gerade wenig zeit das selber zu testen aber mein ansatz wäre folgender:

1. deine artid's in priceforarticle mit einem rank versehen. ich komme von oracle und da gibt es eine funktion dazu. in mysql glaube ich nicht. da musst du dir was basteln: http://stackoverflow.com/questions/3333665/mysql-rank-function
also einfach dafür sorgen dass du am ende pro artid gruppierst. sollte dann für artid 123456781 rank 1-3 geben und für die anderen dann nur 1.
2. eine inline view mit 3 selects. im ersten nimmst du dann alle rows wo rank = 1 und füllst nur was in die spalten perc1, amount1 und amountto1 ab. perc2, amount2, amountto2, per3, amount3, amountto3 sind alle null. im zweiten dann rank=2 und füllst nur perc2, amount2 und amountto2 ab. perc1, amount1, amountto1, perc3, amount3, amountto3 sind alle null und das ganze auch noch für rank=3. verbunden jeweils mit union all.
3. das finale select wo du nach artid gruppierts und alle anderen summierst (also perc1 ... amountto3). wenn du dann noch magst kannst du die numbers noch zu varchar konvertieren und amount und amountto zusammenfassen
 
Ungetestet aus dem Stehgreif
SQL:
SELECT
	artid,
	-- Wenn die pos 1 ist, nimm den Text. Das ergibt eine Eintrag mit Text und viele mit ''.
	-- Darum nehmen wir davon och den MAX() um wirklich den Text zu kriegen
	MAX(IF(pos=1, perc_s, ''))		AS perc_1,
	MAX(IF(pos=1, amount_s, ''))	AS amount_1,
	MAX(IF(pos=2, perc_s, ''))		AS perc_2,
	MAX(IF(pos=2, amount_s, ''))	AS amount_2,
	MAX(IF(pos=3, perc_s, ''))		AS perc_3,
	MAX(IF(pos=3, amount_s, ''))	AS amount_3
FROM
	(
		SELECT
			-- Position innerhalb der gleichen artid
			@pos := IF(@last_artid = artid, @pos + 1, 1)	AS pos,
			-- artid zweischenspeichern
			@last_artid := artid 							AS artid,
			-- perc Ausgabestring zusammensetzen
			CONCAT(perc, ' (%)')							AS perc_s,
			-- amount Ausgabestring zusammensetzen
			CONCAT(amount, '-', amountto, ' (Pc)')			as amount_s
		FROM
			(SELECT @pos := 0, @last_artid := '') AS vars,
			priceforarticle 
		ORDER BY
			artid,
			perc
	) AS prepared_data
GROUP BY
	artid
 
Zuletzt bearbeitet von einem Moderator:
Vielen Dank für die Antwort(en). Leider gibt "er" mir "noch" eine Fehlermeldung aus:

Code:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'priceforarticle ORDER BY artid, perc ' at line 24
 
Wow, das funktioniert. Wie bekomme ich aber die Ausgabe in PHP hin? Ich hatte einen Fehler drin. Danke für den Link
 
Zuletzt bearbeitet:
So wie jedes andere Resultat einer DB-Abfrage in PHP.
Zur Schreibweise, siehe PHP SQL-Statement in PHP lesbar darstellen

PHP:
$sql = <<<SQL
SELECT
    artid,
    -- Wenn die pos 1 ist, nimm den Text. Das ergibt eine Eintrag mit Text und viele mit ''.
    -- Darum nehmen wir davon och den MAX() um wirklich den Text zu kriegen
    MAX(IF(pos=1, perc_s, ''))      AS perc_1,
    MAX(IF(pos=1, amount_s, ''))    AS amount_1,
    MAX(IF(pos=2, perc_s, ''))      AS perc_2,
    MAX(IF(pos=2, amount_s, ''))    AS amount_2,
    MAX(IF(pos=3, perc_s, ''))      AS perc_3,
    MAX(IF(pos=3, amount_s, ''))    AS amount_3
FROM
    (
        SELECT
            -- Position innerhalb der gleichen artid
            @pos := IF(@last_artid = artid, @pos + 1, 1)    AS pos,
            -- artid zweischenspeichern
            @last_artid := artid                            AS artid,
            -- perc Ausgabestring zusammensetzen
            CONCAT(perc, ' (%)')                            AS perc_s,
            -- amount Ausgabestring zusammensetzen
            CONCAT(amount, '-', amountto, ' (Pc)')          AS amount_s
        FROM
            (SELECT @pos := 0, @last_artid := '') AS vars,
            priceforarticle 
        ORDER BY
            artid,
            perc
    ) AS prepared_data
GROUP BY
    artid
SQL;

$result = mysql_query($sql);
....
 
Zurück