Webstatt.org - Community seit 2006 - 2012 (2024?)

Verschatelte MySQL-Abfrage

Avatar user-287
12.12.2006 17:06

Hallo,
Ich habe ungefähr diesen code:


//Head Kategorien
$headcats = $db->query("SELECT * FROM cats WHERE headcatid = '0' ORDER BY sort ASC"zwinkern;
while($rowheadcat = $db->fetch_array($headcats)) {

//Sub Kategorien
$subcats = $db->query("SELECT * FROM cats WHERE headcatid = '$rowheadcat[catid]' ORDER BY sort ASC"zwinkern;

while($rowsubcat = $db->fetch_array($subcats)) {

}
}


Ich kann mir gut vorstellen, dass das ganz schön den server auslasten kann im extremfall. Geht das auch irgendwie geschickter? Per Join (was ich mir noch nicht vorstellen kann)
Oder ist die schleife die einzige lösung?

Avatar user-236
12.12.2006 17:34

Hi,

klar geht das auch mit besserer Performance, aber dazu ist dein DB Schema momentan verkehrt, würd ich auf den ersten Blick sagen. Ist es nicht besser die subkategorien in einer anderen Tabelle zu speichern? user-158n kannst du ohne Problem per left join die Daten holen:

Beispiel
cat
-----
id | name | text

subcat
-------
id | cid |name| text

$query = "SELECT a.*, b.* FROM cat AS a LEFT JOIN subcat AS b ON a.id = b.cid";

Dann musst du nur schauen, dass die subcats den normalen cats richtig zugeordnet werden, das ist eigentlich alles:

cat:
-----------
12 | natur | das ist die natur

sub cat
--------------
1 | 12 | bach | ein bach
2 | 12 | baum| ein baum

Alles klar ? lächeln

Grüße,
mab

signature in progress
Avatar user-287
12.12.2006 17:49

würde dann bei der Methode mehr als ein Subcat aus der db ausgelesen werden?

Avatar user-236
12.12.2006 17:57

ja, wenn ich das Statement richtig gemacht hab schon. das heißt so viel wie:

nehm den eintrag aus cat und alle subcats deren cid der id von cat entspricht:

ausgabe:

=> natur
- bach
- baum

signature in progress
Avatar user-287
12.12.2006 18:15

Original von user-236
ja, wenn ich das Statement richtig gemacht hab schon. das heißt so viel wie:

nehm den eintrag aus cat und alle subcats deren cid der id von cat entspricht:

ausgabe:

=> natur
- bach
- baum


versteh nur nicht wie dann die ausgabe laufen soll, wo werden dann die "bäume" gespeichert? in nem array?

Avatar user-236
12.12.2006 19:21

left join sorgt dafür dass alle einträge mit der rechten tabelle "gematched" werden. sollte keine subcat zu der cat bestehen, wird null geliefert. die daten kannst du ganz normal ausgeben. teste doch einfach mal... du brauchst nichts zu beachten, außer die reihenfolge bei LEFT JOIN ON ....

signature in progress
Avatar user-287
12.12.2006 19:52

Original von user-236
left join sorgt dafür dass alle einträge mit der rechten tabelle "gematched" werden. sollte keine subcat zu der cat bestehen, wird null geliefert. die daten kannst du ganz normal ausgeben. teste doch einfach mal... du brauchst nichts zu beachten, außer die reihenfolge bei LEFT JOIN ON ....


Geht das denn nichtmit Headcats und Subcats in einer Tabelle?
Denn außer der äußerlichen formatierung auf der Seite unterscheiden die sich nicht und da ist die verwaltung mit einer tabelle einfacher.

Avatar user-236
13.12.2006 17:56

klar, das kannst du machen, wie du es einfacher findest.
ich find es mit zwei Tabellen nicht nur geschickter, so ist es auch korrekt. je nach umfang deines projektes, kann es sein, dass mit der zeit kleine problemchen auftreten.

signature in progress
Avatar user-287
13.12.2006 17:57

Original von user-236
klar, das kannst du machen, wie du es einfacher findest.
ich find es mit zwei Tabellen nicht nur geschickter, so ist es auch korrekt. je nach umfang deines projektes, kann es sein, dass mit der zeit kleine problemchen auftreten.


Es werden glaub ich max. 20-30 einträge geben in der Tabelle, bringt es was bei dieser größenordnung?

Avatar user-236
13.12.2006 18:04

keine Ahnung, denke eher weniger. Du kannst ja die Geschwindigkeit messen Fettes Grinsen

Es kommt eigentlich nur drauf an, ob du jetzt ein gescheites Tabellen Design möchtest oder du dich mit so nem Mix zufrieden gibst. Mehr gibts dazu nicht zu sagen. :tired:

signature in progress
Avatar user-287
14.12.2006 12:55

Original von user-236
keine Ahnung, denke eher weniger. Du kannst ja die Geschwindigkeit messen Fettes Grinsen

Es kommt eigentlich nur drauf an, ob du jetzt ein gescheites Tabellen Design möchtest oder du dich mit so nem Mix zufrieden gibst. Mehr gibts dazu nicht zu sagen. :tired:


wirklich zufrieden bin ich nicht, aber auch zu faul alles zu ändern^^
Aber ich denke ich werds ändern.

Avatar user-287
25.12.2006 10:43

Bin grade dabei es zu ändern, aber irgendwas stimmt da nicht:


$cats = $db->query("SELECT * FROM headcats LEFT JOIN subcats ON(headcats.catid = subcats.headcatid) ORDER BY headcats.sort ASC, subcats.sort ASC"zwinkern;

while($rowcat = $db->fetch_array($cats)) {

$tpl->set_bit("tablecolor", table_ab());
$tpl->set_bit("cat_id", $rowcat['catid']);
$tpl->set_bit("cat_catname", $rowcat['catname']);

$tpl->getbit("navi_cats_showbit", "navi_cats_showbit"zwinkern;

}


gibt folgenden array aus:


Array
(
[0] => 3
[catid] =>
[1] => test4
[catname] =>
[2] => 0
[sort] =>
[3] =>
[4] =>
[5] =>
[headcatid] =>
[6] =>
)


Headcats:

catid catname sort
1 test1 2
2 test3 1
3 test4 0
4 asdasdasd 0


subcats:

catid catname headcatid sort
1 aaa 1 2
2 bbbb 1 1

Avatar user-236
25.12.2006 12:06

mh, kann im Moment nicht viel erkennen. Aber schau für den Anfang , dass für jeden Eintrag aus cat ein Eintrag aus subcat existiert!!! Die Sortierung am Anfang mal weglassen, auf die Reihenfolge beim Join achten.

signature in progress
Avatar user-287
25.12.2006 12:09

Original von user-236
mh, kann im Moment nicht viel erkennen. Aber schau für den Anfang , dass für jeden Eintrag aus cat ein Eintrag aus subcat existiert!!! Die Sortierung am Anfang mal weglassen, auf die Reihenfolge beim Join achten.


Nicht jede Headcat hat momentan auch subcats, kann man das auch machen, dass es nicht so sein muss?

Avatar user-236
25.12.2006 12:20

das müsste mit Inner Join gehen. Damit werden dann aber die "leeren" Einträge ganz ausgelassen. Am besten du liest dich mal dort ein: http://www.sql-tips.de/index.php/INNER_JOIN_-_OUTER_JOIN

Wenn es mal funktoniert, dann hast du echt ne ordentliche Abfrage.. ich find das lohnt sich schon.

signature in progress
Avatar user-287
27.12.2006 09:32

ich komm damit echt nicht zurecht, könnt das mal einer für mich machen, der weiß wie es geht?

Problem ist, dass er immer nur die subcats oder nur die headcats ausgibt. Hab schon alle joins ausprobiert, oder ich bin einfach zu blöd, um die daten auszugeben.
Also gibt mal bitte einer ne Lösung.

Das Problem könnte auch sein, dass z.B. jedem headcat mehrere subcats zugeordnet werden, ich aber pro headcat nur ein schleifendurchlauf habe und in diesem durchlauf nicht die subcats ausgebe.
Wie kann ich dann in einem schleifendurchlauf die subcats ausgeben?

Avatar user-287
28.12.2006 11:15

Ok, Ich bin schonmal ein stück weiter, jedoch scheitert es noch an der Ausgabe.

Momentan sieht es so aus:

$cats = $db->query("SELECT h.*, s.* FROM headcats AS h LEFT JOIN subcats AS s ON h.headcatid = s.headcatid GROUP BY h.headcatid, s.headcatid ORDER BY h.headcatsort ASC, s.subcatsort ASC"zwinkern;

while($rowcat = $db->fetch_array($cats)) {

$tpl->set_bit("tablecolor", table_ab());
$tpl->set_bit("cat_id", $rowcat['catid']);
$tpl->set_bit("cat_catname", $rowcat['headcatname'].' '.$rowcat['subcatname']);

$tpl->getbit("navi_cats_showbit", "navi_cats_showbit_subcats"zwinkern;

}


Problem ist, das er die von de subcats immer nur 1 ausgibt.
Muss man die subcats (weils mehrere sein werden) in einen array packen? Wie mach ich das?

Also Ausgabe ist dann so:

headcat4 subcat1
headcat4 subcat2
headcat3
headcat1

Ich bräuchte das so:
headcat4
subcat1
subcat2
headcat3
headcat1

Avatar user-236
28.12.2006 12:03

Hi..

Irgendwie versteh ich grad nicht wo es hängt :rolleyes: Kannst du noch mal deine Tabellen mit Einträgen zeigen.. schön geordnet.

signature in progress
Avatar user-287
28.12.2006 12:16

Original von user-236
Hi..

Irgendwie versteh ich grad nicht wo es hängt :rolleyes: Kannst du noch mal deine Tabellen mit Einträgen zeigen.. schön geordnet.


subcats:

subcatid subcatname headcatid subcatsort
1 aaa 3 2
2 bbbb 3 1


headcats:

headcatid headcatname headcatsort
1 test1 2
2 test3 1
3 test4 0


Die TAbellen sollten eiegntlich stimmen, das Problem ist, dass er die subcats nicht ohne headcat ausgibt wie in den Beispiel was ich zuvor gemacht hatte.

Avatar user-236
28.12.2006 14:07

ok, verstehe. versuch mal das

über Gruppierung


$cats = $db->query("SELECT h.*, s.* FROM headcats AS h LEFT JOIN subcats AS s ON h.headcatid = s.headcatid GROUP BY h.headcatname"zwinkern;


Falls das nicht taugt dann über DISTINCT



$cats = $db->query("SELECT DISTINCT h.headcatname, s.* FROM headcats AS h LEFT JOIN subcats AS s ON h.headcatid = s.headcatid"zwinkern;



Wenn das auch nicht hilft, dann hab ich keine Ahnung Fettes Grinsen Du musst die Abfrage um deine entsprechenden Felder erweitern.

Hope it helps zwinkern

Grüße,
mab

signature in progress
Avatar user-287
28.12.2006 16:49

Hab das nun so versucht zu lösen, was aber nciht richtig funktioniert:


$cats = $db->query("SELECT h.*, s.* FROM headcats AS h LEFT JOIN subcats AS s ON h.headcatid = s.headcatid ORDER BY h.headcatsort ASC, s.subcatsort ASC"zwinkern;

while($rowcat = $db->fetch_array($cats)) {


if($last_headcatid != $rowcat['headcatid'])
{
$tpl->set_bit("tablecolor", table_ab());
$tpl->set_bit("cat_id", $rowcat['catid']);

$tpl->set_bit("cat_catname", $rowcat['headcatname']);

$tpl->getbit("navi_cats_showbit", "navi_cats_showbit_subcats"zwinkern;
}
if(!empty($rowcat['subcatid']))
{
$tpl->set_bit("tablecolor", table_ab());
$tpl->set_bit("cat_id", $rowcat['catid']);

$tpl->set_bit("cat_catname", $rowcat['subcatname']);

$tpl->getbit("navi_cats_showbit", "navi_cats_showbit_subcats"zwinkern;
}
$last_headcatid = $rowcat['headcatid'];
}

Avatar user-236
28.12.2006 16:55

das mit distinct ging nicht?? hab ähnliche statements selbst im einsatz. mh hauptsache es läuft jetzt lächeln

signature in progress
Avatar user-287
28.12.2006 17:46

Original von user-236
das mit distinct ging nicht?? hab ähnliche statements selbst im einsatz. mh hauptsache es läuft jetzt lächeln


Gab mir genau die gleiche ausgabe. Aber bin so momentan noch nicht zufrieden, da irgendwie nicht alles angezeigt wird.

Avatar user-236
28.12.2006 18:32

Du kannst auch mal alle Daten über phpMyAdmin abspeichern und hier als *rar anhängen. So dass ich halt bei mir gleich den Insert machen kann.
Dann schau ich drauf, falls ich Zeit hab zwinkern

signature in progress
Avatar user-287
28.12.2006 18:40


--
-- Tabellenstruktur für Tabelle `headcats`
--

CREATE TABLE `headcats` (
`headcatid` int(11) NOT NULL auto_increment,
`headcatname` varchar(50) NOT NULL default '',
`headcatsort` int(11) NOT NULL default '0',
PRIMARY KEY (`headcatid`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

--
-- Daten für Tabelle `headcats`
--

INSERT INTO `headcats` (`headcatid`, `headcatname`, `headcatsort`) VALUES (1, 'test1', 0);
INSERT INTO `headcats` (`headcatid`, `headcatname`, `headcatsort`) VALUES (2, 'test3', 1);
INSERT INTO `headcats` (`headcatid`, `headcatname`, `headcatsort`) VALUES (3, 'test4', 0);

-- --------------------------------------------------------

--
-- Tabellenstruktur für Tabelle `subcats`
--

CREATE TABLE `subcats` (
`subcatid` int(11) NOT NULL auto_increment,
`subcatname` varchar(50) NOT NULL default '',
`headcatid` int(11) NOT NULL default '0',
`subcatsort` int(11) NOT NULL default '0',
PRIMARY KEY (`subcatid`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Daten für Tabelle `subcats`
--

INSERT INTO `subcats` (`subcatid`, `subcatname`, `headcatid`, `subcatsort`) VALUES (1, 'aaa', 3, 2);
INSERT INTO `subcats` (`subcatid`, `subcatname`, `headcatid`, `subcatsort`) VALUES (2, 'bbbb', 3, 1);


Avatar user-287
29.12.2006 11:24

OK, das Problem war, dass der name spalte bei den subcats "headcatid" und die Spalte bei den headcats "headcatid" war. Hab die Spalte bei den subcats in "subhcatid" umbenannt und es gibt keine Probleme mehr. (Hatte mir schon gedacht, dass es da Probleme geben kann).

Danke an die fleißigen Helfer! Konnte die Anzahl der mysql abfragen auf die hälfte reduzieren (Insgesamt)