anpera.net
https://anpera.dyndns.org/phpbb3/

Tabellenübergreifende Sortierung
https://anpera.dyndns.org/phpbb3/viewtopic.php?f=34&t=3649
Seite 1 von 1

Autor:  Bill Tür [ So 20 Mai, 2007 22:34 ]
Betreff des Beitrags:  Tabellenübergreifende Sortierung

Ich hab folgende Tabelle gemacht:

[php]
$sql = "SELECT name,acctid,guildtag,guildowner,guildleader,guildname FROM accounts ".
"LEFT JOIN guilds on accounts.guildid = guilds.guildid ".
"WHERE accounts.guildid>0 ORDER BY guilds.guildid ASC";
$result = db_query($sql) or die(sql_error($sql));
output("<table border=0 cellpadding=2 cellspacing=1 bgcolor='#999999'>",true);
output("<tr class='trhead'><td><b>Gilde</b></td><td><b>Tag</b></td><td><b>Name</b></td><td><b>Status</b></tr>",true);
for($i=0;$i<db_num_rows($result);$i++){
$row = db_fetch_assoc($result);
output("<tr class='".($i%2?"trdark":"trlight")."'><td>",true);
output("`^$row[guildname]`0");
output("</td><td>",true);
output("`^$row[guildtag]`0");
output("</td><td>",true);
output("`&$row[name]`0");
output("</td><td>",true);
IF ($row[guildowner]==$row[acctid]) {
output("`oGildenleiter");
}ELSEIF ($row[guildleader]==$row[acctid]) {
output("`QStellvertreter");
}ELSE{
output("`SMitglied");
}
output("</td></tr>",true);
}
output("</table>",true);
[/php]

funzt auch ganz toll, wie man sieht:

Bild

Nur hätte ich das ganze gern noch nach Gildenleiter und Stellvertreter sortiert.

Ich habs so probiert:

[php]
$sql2 = "SELECT accounts.acctid,accounts.guildid,guilds.guildowner,guilds.guildleader FROM accounts LEFT JOIN guilds on guilds.guildid = accounts.guildid WHERE accounts.guildid>0";
$result2 = db_query($sql2) or die(sql_error($sql2));
$row2 = db_fetch_assoc($result2);
IF ($row2['guildowner']==$row2['acctid']) $guildstat='1';
IF ($row2['guildleader']==$row2['acctid']) $guildstat='2';
IF (($row2['guildowner']!=$row2['acctid']) && ($row2['guildleader']!=$row2['acctid'])) $guildstat='3';

$sql = "SELECT name,acctid,guildtag,guildowner,guildleader,guildname FROM accounts ".
"LEFT JOIN guilds on accounts.guildid = guilds.guildid ".
"WHERE accounts.guildid>0 ORDER BY guilds.guildid ASC, $guildstat ASC";
//... ab hier gehts weiter wie oben
[/php]


Aber das hat mal gar keinen Effekt. Ist das nun völliger Blödsinn, oder bin ich wenigstens auf dem richtigen Weg?

Autor:  Auric [ Mo 21 Mai, 2007 00:00 ]
Betreff des Beitrags: 

Uff, gibt es nicht für die einzelnen Ränge keine IDs?

Ansonsten könnte ich dir empfehlen, per IF/ELSE eine integer Rang-Variable zu definieren und danach zu Sortieren.

Keine ahnung, ob es vieleicht eine elegantere Lösung gibt, aber damit könne man es ja vieliecht mal probieren.

Auric :wink:

Autor:  Bill Tür [ Mo 21 Mai, 2007 08:14 ]
Betreff des Beitrags: 

genau da is ja das prob. in der accounts steht nur, in welcher gilde der betreffende ist und in der gildentabelle steht nur acctid xy ist owner und acctid yz ist leader.

Autor:  Leen [ Mo 21 Mai, 2007 08:22 ]
Betreff des Beitrags: 

Mein Vorschlag war halt gewesen, pro Gilde eine Tabelle zu machen und über die Tabelle den Führer und Gründer extra auszuspucken

Achja das kann man natürlich auch in einer Kombination so machen, dass wie jetzt alle Gilden untereinander aufgereiht sind, aber halt die Tabellenstruktur unterbrochen ist @ Gildenführer/-gründer

Autor:  Eliwood [ Mo 21 Mai, 2007 08:47 ]
Betreff des Beitrags: 

Teste mal den QUery hier:

$this->bbcode_second_pass_code('', 'SELECT
a.name,
a.acctid,
a.guildtag,
a.guildowner,
a.guildleader,
a.guildname,
IF(a.acctid = g.owner, 2, IF(a.acctid = g.guildowner, 1, 0)) AS 'rangstatus'
FROM
accounts a
LEFT JOIN
guilds g
ON
a.guildid = g.guildid
WHERE
a.guildid>0
GROUP BY
a.guildid ASC
ORDER BY
a.guildid ASC, IF(a.acctid = g.owner, 2, IF(a.acctid = g.guildowner, 1, 0))')

Autor:  Bill Tür [ Mo 21 Mai, 2007 09:10 ]
Betreff des Beitrags: 

@ Leen: bin ich am Sonntag nicht mehr dazu gekommen, aber als Plan B hab ichs noch im Hinterkopf, falls ich hier keine praktikablere Lösung finde ;)

@ Eliwood: habs leicht abgeändert (die Tabellenfelder/Zuordnung hat nicht ganz gepasst und das Group musste ich ausklammern, da er sonst nur eine Zeile pro Gilde angezeigt hat mit jeweils dem ersten Mitglied).

nu siehts so aus:

[php]
$sql = "SELECT
a.name,
a.acctid,
g.guildtag,
g.guildowner,
g.guildleader,
g.guildname,
IF(a.acctid = g.guildowner, 2, IF(a.acctid = g.guildleader, 1, 0)) AS 'rangstatus'
FROM
accounts a
LEFT JOIN
guilds g
ON
a.guildid = g.guildid
WHERE
a.guildid>0
/*GROUP BY
a.guildid ASC*/
ORDER BY
a.guildid ASC, IF(a.acctid = g.guildowner, 2, IF(a.acctid = g.guildleader, 1, 0))";
[/php]

aber leider sieht die tabelle exakt aus wie vorher.

Autor:  Leen [ Mo 21 Mai, 2007 09:39 ]
Betreff des Beitrags: 

@ Eliwood

Wieso in der letzten Zeile nochmal die IFs?? Hast doch vorher schon 'rangstatus' bestimmt, sollte doch gehen, wenn du in der letzten Zeile auch danach sortierst oder?

Autor:  Bill Tür [ Mo 21 Mai, 2007 09:48 ]
Betreff des Beitrags: 

der Gedanke kam mir auch schon, doch

[php]
ORDER BY
a.guildid ASC, 'rangstatus' ASC";
[/php]

hat nichts gebracht.

Autor:  Auric [ Mo 21 Mai, 2007 12:41 ]
Betreff des Beitrags: 

Nee, die selbst erstellten speudo-Spalten kann man leider nicht in der ORDER BY-Klausel verwenden, glaube ich.

Autor:  Eliwood [ Mo 21 Mai, 2007 16:18 ]
Betreff des Beitrags: 

OKay. Ohne Group gehts dann natürlich nicht...

Meine Testtabellen:

$this->bbcode_second_pass_code('', 'CREATE TABLE `accounts` (
`acctid` int(11) NOT NULL auto_increment,
`guildid` int(11) NOT NULL,
PRIMARY KEY (`acctid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=9 ;

INSERT INTO `accounts` (`acctid`, `guildid`) VALUES
(1, 1),
(2, 1),
(3, 1),
(4, 1),
(5, 2),
(6, 2),
(7, 2),
(8, 2);

CREATE TABLE `guilds` (
`guildid` int(11) NOT NULL auto_increment,
`guildleader` int(11) NOT NULL,
`guildowner` int(11) NOT NULL,
PRIMARY KEY (`guildid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=3 ;

INSERT INTO `guilds` (`guildid`, `guildleader`, `guildowner`) VALUES
(1, 2, 3),
(2, 7, 8);
')

Mein QUery:
$this->bbcode_second_pass_code('', 'SELECT
a.acctid,
IF(a.acctid = g.guildowner, 2, IF(a.acctid = g.guildleader, 1, 0)) AS 'rangstatus'
FROM
accounts a
LEFT JOIN
guilds g
ON
a.guildid = g.guildid
WHERE
a.guildid>0
ORDER BY
a.guildid ASC, IF(a.acctid = g.guildowner, 2, IF(a.acctid = g.guildleader, 1, 0)) DESC')

Ausgabe =>
$this->bbcode_second_pass_code('', 'Acctic Guildid
3 2
2 1
1 0
4 0
8 2
7 1
5 0
6 0')

Funktioniert also. In der Testumgebung?!

@Leen: Ja, Auric hat recht. "Pseudospalten" lassen sich nicht in der Order-By-Klausen verwenden, weshalb man die If m.E. nochmal anwenden muss.

EDIT: Geht anscheinend doch O.o Zumindest mit MySQL v.5.0.27:

$this->bbcode_second_pass_code('', 'SELECT
a.acctid,
IF(a.acctid = g.guildowner, 2, IF(a.acctid = g.guildleader, 1, 0)) AS 'rangstatus'
FROM
accounts a
LEFT JOIN
guilds g
ON
a.guildid = g.guildid
WHERE
a.guildid>0
ORDER BY
a.guildid ASC, 'rangstatus' DESC')

Strange... :D

Autor:  Bill Tür [ Mi 23 Mai, 2007 10:57 ]
Betreff des Beitrags: 

Nachdem irgendwie alles nicht so hingehauen hat, wie ich das wollte, hab ichs jetzt so gelöst:

[php]
$sql = "UPDATE accounts SET guildstat=0 WHERE guildstat=1 OR guildstat=2";
db_query($sql);

$sql = "SELECT guildowner,guildleader FROM guilds";
$result = db_query($sql);
for($i=0;$i<db_num_rows($result);$i++){
$row = db_fetch_assoc($result);
$sql = "UPDATE accounts SET guildstat=1 WHERE acctid='$row[guildleader]'";
db_query($sql);
$sql = "UPDATE accounts SET guildstat=2 WHERE acctid='$row[guildowner]'";
db_query($sql);
}


$sql = "SELECT name,login,guildstat,acctid,guildtag,guildowner,guildleader,guildname FROM accounts ".
"LEFT JOIN guilds on accounts.guildid = guilds.guildid ".
"WHERE accounts.guildid>0 ORDER BY guilds.guildid ASC, guildstat DESC, login ASC";
$result = db_query($sql) or die(sql_error($sql));
output("<table border=0 cellpadding=2 cellspacing=1 bgcolor='#999999'>",true);
output("<tr class='trhead'><td><b>Gilde</b></td><td><b>Tag</b></td><td><b>Name</b></td><td><b>Status</b></tr>",true);
for($i=0;$i<db_num_rows($result);$i++){
$row = db_fetch_assoc($result);
output("<tr class='".($i%2?"trdark":"trlight")."'><td>",true);
output("`^$row[guildname]`0");
output("</td><td>",true);
output("`^$row[guildtag]`0");
output("</td><td>",true);
output("`&$row[name]`0");
output("</td><td>",true);
IF ($row[guildowner]==$row[acctid]) {
output("`oGildenleiter");
}ELSEIF ($row[guildleader]==$row[acctid]) {
output("`^Stellvertreter");
}ELSE{
output("`GMitglied");
}
output("</td></tr>",true);
}
output("</table>",true);
[/php]

Sicher nicht die eleganteste Lösung, aber dafür funktioniert sie ^^

Danke nochmal allen Beteiligten ;)

Autor:  Nightborn [ Mi 23 Mai, 2007 12:17 ]
Betreff des Beitrags: 

$this->bbcode_second_pass_code('', 'for($i=0;$i<db_num_rows($result);$i++){
')

<--- unnötige funktionsaufrufe: $i

$this->bbcode_second_pass_code('', '$k=db_num_rows($result);
for($i=0;$i<$k;$i++){
')

<--- unnötige funktionsaufrufe: 0

Autor:  Bill Tür [ Mi 23 Mai, 2007 12:26 ]
Betreff des Beitrags: 

kannst du das ganz kurz erläutern? ich würd solche Sachen für die Zukunft gern verstehen :)

Autor:  Harthas [ Mi 23 Mai, 2007 13:06 ]
Betreff des Beitrags: 

[php]for($i=0;$i<db_num_rows($result);$i++){ [/php]

Hier wird db_num_rows bei jedem Durchlauf der Schleife ausgeführt. Bei folgendem nur noch genau !1! Mal, und der Wert wird dann in die Variable k gespeichert.
[php]
$k=db_num_rows($result);
for($i=0;$i<$k;$i++){ [/php]

Autor:  Bill Tür [ Mi 23 Mai, 2007 14:53 ]
Betreff des Beitrags: 

@Nightborn u Harthas: Thx für die Info. Kann ich das eigtl überall ersetzen, wo
[php]for($i=0;$i<db_num_rows($result);$i++){[/php]
steht? das ist ja quer übers logd verteilt. oder nur in diesem speziellen fall?

@ Topic: ja, warum einfach, wenns auch umständlich geht. ich hab das ganze mal nen bekannten anschaun lassen, der hat mich gleich mal verlacht und mir auf die schnelle das hier hingekritzelt:

[php]
$sql="SELECT name,login,guildstat,acctid,guildtag,guildowner,guildleader,guildname,
(guilds.guildleader = accounts.acctid) as vertretervergleich,
(guilds.guildowner = accounts.acctid) as leadervergleich from accounts
LEFT JOIN guilds on accounts.guildid = guilds.guildid
WHERE accounts.guildid > 0
ORDER BY guilds.guildid ASC, leadervergleich DESC, vertretervergleich DESC, login ASC";
[/php]

Er arbeitet halt beruflich mit PHP und SQL

Ich habs mal eingebaut und ja, es geht. naja, nun hab ich zwei Lösungen. *gg*

Autor:  Auric [ Mi 23 Mai, 2007 16:27 ]
Betreff des Beitrags: 

Nach Eliwoods Heinweis funktioniert das ab MySQL 5 - ich weiß allerdings nicht, wie es mit der abwärtskompatiblität aussieht. Na was solls, bei dir funzt es ja ^^

bez. for-Schleife:
Ja, das kannst du im prinzip überall austauschen, da es wie oben beschrieben performanter ist - zumindest solange kein mysqli-objekt verwendet wird, so der Vorteil nur marginal sein dürfte.
[Erklärung: Beim mysqli_result-objekt ist num_rows eine skalare Eigenschaft, es wird also ebenfalls nur eine (Instanz-)Variabe gelesen, die für php aufbereitet zu verfügung steht.

Autor:  Eliwood [ Mi 23 Mai, 2007 17:20 ]
Betreff des Beitrags: 

Intressante Lösung @ Bill Tür. Was für ne MySQL-Version hast du? ZUmindest ab 5.0 geht meine. Welche nun schöner ist, ist Meinungssache :D

(Hat wer hier garantiert ne neue MySQL 4 und kann kurz meine Testtabellen nachtesten?)

Autor:  Bill Tür [ Mi 23 Mai, 2007 19:28 ]
Betreff des Beitrags: 

@ Auric: Thx für die Info

@Eliwood:

phpMyAdmin hat geschrieben:
Verbunden mit MySQL 4.0.23-Max-log auf localhost

Seite 1 von 1 Alle Zeiten sind UTC + 1 Stunde
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/