CPagination

Hi,

ich erarbeite mir grad eine Admin-Oberfläche und stoße auf ein Pagination-Problem mit einem Join der auf die gleiche Tabelle verlinkt.

Zu meiner Vorgehensweise.

  1. Ich habe ein modules Ordner angelegt und dort mein Admin-Ordner von gii anlegen lassen.

  2. Ich erstelle für meine Tabellen etc, geeignete CRUD-Oberflächen

  3. Für das Auflisten im Admin-Bereich von meinen Werten aus den Tabellen benötige ich einen Join. Da die relations() in der Tabelle basic definiert sind, kann ich darauf nicht zugreifen:




public function relations()

{

	return array(

		'trans'	=> array(self::MANY_MANY, 'basic', 'basic_basic( basic1Id, basic2Id )',

			'together'	=> true,

			'joinType'	=> 'INNER JOIN',

		),

}

Meine Tabellen sehen folgendermaßen aus. Basic wird über einen Join mit basic zurück verknüpft

basic

id

value

typ

basic_basic

basic1Id

basic2Id

Da ich im Admin-Bereich nicht auf die Relation trans aus meinem Model basic zurückgreifen kann (yii wirft eine Fehlermeldung zurück, dass es die Relation trans nicht gibt), habe ich die Methode im Model basic definiert:


public function getPagination( $aTypes )

{

	$oCriteria	= new CDbCriteria;

	$oCriteria->alias = 'b';

	$oCriteria->addInCondition( "b.typ", $aTypes);

	$oCriteria->addInCondition( "trans.typ", $aTypes );


	$pages = new CPagination(basic::model()->with(array('trans'))->count($oCriteria));

	$pages->pageSize=25;

	$oPages = $pages->applyLimit($oCriteria);


	$sort = new CSort('Basic');

	$sort->defaultOrder = 'b.id ASC';

	$oSort = $sort->applyOrder($oCriteria);


	$oModel = basic::model()->with(array('trans'))->findAll($oCriteria);

	

	return array($oPages, $oSort, $oModel);

}

Hier tritt auch das Problem nun auf.

Er listet mir entweder nicht alles auf, oder es bricht auf.

Ich vermute das das Problem daran liegt, das er zuerst den kompletten Join für alle Werte ausführt und dann erst begrenzt, was aber keinen Sinn machen würde.

Dieser Join generiert er daraus was ja auch richtig ist, aber der Join verbindet erst alles und beschränkt dann erst die Auswahl


SELECT * FROM `basic` `b` 

INNER JOIN `basic_basic` `trans_trans` ON

(`b`.`id`=`trans_trans`.`basic1Id`) INNER JOIN

`basic` `trans` ON

(`trans`.`id`=`trans_trans`.`basic2Id`)  WHERE

((b.typ IN (:ycp2,:ycp3)) 

AND (trans.typ IN (:ycp2,:ycp3))) 

ORDER BY b.id ASC LIMIT 25

Fakten zu den Tabellen:

basic hast ca. 400.000 Einträge

basic_basic ca. 1.200.000 Einträge

Ich hoffe ihr könnt mir hier weiterhelfen.

thx

Problem ist vermutlich:

Du kannst HAS_MANY/MANY_MANY-Relationen nicht mit der Haupttabelle laden (eager loading bzw. together), wenn du Pagination verwenden willst. Das ist kein Yii-Problem, sondern ein prinzipielles. Es ist nicht möglich, das in einer einzelnen SQL-Abfrage mit JOINs + LIMIT zu machen, da für jeden Eintrag in der Haupttabelle mehrere Einträge in der Nebentabelle (also mehrere Zeilen im Ergebnis) rangejoined werden können. LIMIT macht dann nicht mehr das, was man erwarten würde.

kannst du mir eine Lösung vorschlagen?

Kommt drauf an, was du machen willst. Mir fallen zwei Sachen ein:

a ) lazy loading

b ) evtl. hilft dir ein group auf t.id und GROUP_CONCAT()

b ) ist ganz witzig. Spiel damit am besten erst mal mit reinem SQL z.B. in phpMyAdmin rum, damit du siehst, was das macht.