Problem with LIMIT

Hi guys, i build a website with a search feature but i have a problem with the LIMIT in my query. There are 8000+ items in my database and based on the search criterea i want to show the user always 100 items.

But at the moment it’s always showing less then the LIMIT 100 i set.

EDIT: when i fire the query directly in PHPMyadmin i get 100 results…

query


Querying SQL: SELECT `t`.`IdDaytrip` AS `t0_c0`, `t`.`Daytrip` AS `t0_c1`,

`t`.`Street` AS `t0_c3`, `t`.`Number` AS `t0_c4`, `t`.`ZipCode` AS `t0_c6`,

`t`.`YouTube` AS `t0_c11`, `t`.`Active` AS `t0_c14`, `t`.`Phone` AS

`t0_c7`, geodistkm(52.360194719, 4.88891601562, rCity.Latitude,

rCity.Longitude) AS Distance, `rCity`.`IdCity` AS `t1_c0`,

`rCity`.`CountryId` AS `t1_c1`, `rCity`.`Province` AS `t1_c2`,

`rCity`.`Municipality` AS `t1_c3`, `rCity`.`City` AS `t1_c4`,

`rCity`.`Deeplink` AS `t1_c5`, `rCity`.`Latitude` AS `t1_c6`,

`rCity`.`Longitude` AS `t1_c7`, `rCity`.`GoogleMatch` AS `t1_c8`,

`rCategory`.`IdCategory` AS `t2_c0`, `rCategory`.`Category` AS `t2_c1`,

`rTag`.`IdTag` AS `t3_c0`, `rTag`.`Tag` AS `t3_c1` FROM `Daytrips` `t` 

LEFT OUTER JOIN `Cities` `rCity` ON (`t`.`CityId`=`rCity`.`IdCity`)  INNER

JOIN `DaytripCategory` `rCategory_rCategory` ON

(`t`.`IdDaytrip`=`rCategory_rCategory`.`DaytripId`) INNER JOIN `Categories`

`rCategory` ON

(`rCategory`.`IdCategory`=`rCategory_rCategory`.`CategoryId`)  INNER JOIN

`DaytripTag` `rTag_rTag` ON (`t`.`IdDaytrip`=`rTag_rTag`.`DaytripId`) INNER

JOIN `Tags` `rTag` ON (`rTag`.`IdTag`=`rTag_rTag`.`TagId`)  WHERE (Active =

1 AND rCategory.IdCategory IN (1,2,3,4,5,6)) ORDER BY Distance ASC,

Priority DESC, RAND(), CategoryId, Tag LIMIT 100

Controller


$criteria = new CDbCriteria(array(

                            'condition' => 'Active = 1 AND rCategory.IdCategory IN ('.$cats.')',

                            'order' => 'Distance ASC, Priority DESC, RAND()',

                            'limit' => 100

            ));

$daytrips = Daytrip::model()->distance()->with(array('rCity', 'rCategory', 'rTag'))->together()->findAll($criteria);

Model


    public function relations() {

	return array(

		'rCity' => array(self::BELONGS_TO, 'City', 'CityId'),

		'rCategory' => array(self::MANY_MANY, 'Category', 'DaytripCategory(DaytripId, CategoryId)',

			'joinType' => 'INNER JOIN',

			'order' => 'CategoryId',

		),

		'rTag' => array(self::MANY_MANY, 'Tag', 'DaytripTag(DaytripId, TagId)',

			'joinType' => 'INNER JOIN',

			'order' => 'Tag'

		),

	);

    }




    public function scopes() {

	return array(

		'distance' => array(

			'select' => array('IdDaytrip', 'Daytrip', 'Street', 'Number', 'ZipCode', 'YouTube', 'Active', 'Phone', new CDbExpression("geodistkm($this->Latitude, $this->Longitude, rCity.Latitude, rCity.Longitude) AS Distance")),

		)

	);

    }

Try this :

$criteria = new CDbCriteria(array(

                        'condition' => 'Active = 1 AND rCategory.IdCategory IN ('.$cats.')',


                        'order' => 'Distance ASC, Priority DESC, RAND()',


                        'limit' => 100


        ));

//$daytrips = Daytrip::model()->distance()->with(array(‘rCity’, ‘rCategory’, ‘rTag’))->together()->findAll($criteria);

$daytrips = Daytrip::model()->distance()->with(array(‘rCity’, ‘rCategory’, ‘rTag’))->findAll($criteria);

then i get the following error:

CDbCommand faalde tijdens het uitvoeren van volgend SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘rCategory.IdCategory’ in ‘where clause’

Then Try:

$criteria = new CDbCriteria(array(

‘condition’ => ‘Active = 1 AND ‘.Category::model()->getTableAlias().’.IdCategory IN (’.$cats.’)’,

‘order’ => ‘Distance ASC, Priority DESC, RAND()’,

‘limit’ => 100

));

$daytrips = Daytrip::model()->distance()->with(array(‘rCity’, ‘rCategory’, ‘rTag’))->findAll($criteria);

no luck.


CDbCommand faalde tijdens het uitvoeren van volgend SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column 't.IdCategory' in 'where clause'

without the together() it’s is not joining the tables categories and tags…

nobody?

It isn’t very orthodox but it will work.

$criteria = new CDbCriteria(array(

‘condition’ => ‘Active = 1 AND rCategory_rCategory.IdCategory IN (’.$cats.’)’,

‘order’ => ‘Distance ASC, Priority DESC, RAND()’,

‘limit’ => 100

));

$daytrips = Daytrip::model()->distance()->with(array(‘rCity’, ‘rCategory’, ‘rTag’))->findAll($criteria);

I assume that ‘IdCategory’ is on the table ‘DaytripCategory’

CDbCommand faalde tijdens het uitvoeren van volgend SQL statement: SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘rCategory_rCategory.IdCategory’ in ‘where clause’

still not joining…


Error in querying SQL: SELECT `t`.`IdDaytrip` AS `t0_c0`, `t`.`Daytrip` AS

`t0_c1`, `t`.`Street` AS `t0_c3`, `t`.`Number` AS `t0_c4`, `t`.`ZipCode` AS

`t0_c6`, `t`.`YouTube` AS `t0_c11`, `t`.`Active` AS `t0_c14`, `t`.`Phone`

AS `t0_c7`, geodistkm(52.7511763453, 4.69116210938, rCity.Latitude,

rCity.Longitude) AS Distance, `rCity`.`IdCity` AS `t1_c0`,

`rCity`.`CountryId` AS `t1_c1`, `rCity`.`Province` AS `t1_c2`,

`rCity`.`Municipality` AS `t1_c3`, `rCity`.`City` AS `t1_c4`,

`rCity`.`Deeplink` AS `t1_c5`, `rCity`.`Latitude` AS `t1_c6`,

`rCity`.`Longitude` AS `t1_c7`, `rCity`.`GoogleMatch` AS `t1_c8` FROM

`Daytrips` `t`  LEFT OUTER JOIN `Cities` `rCity` ON

(`t`.`CityId`=`rCity`.`IdCity`)  WHERE (Active = 1 AND

rCategory_rCategory.IdCategory IN (1,2,3,4,5,6)) ORDER BY Distance ASC,

Priority DESC, RAND() LIMIT 100

when i ad together() it’s executing the query but i get less then 100 records back with yii

Joining a many to many (MANY_MANY) or has many (HAS_MANY) in yii is a disaster (it breaks limits and paging). We had the same issue and tried extending a bunch of the base classes but could never get it to work (I’m sure it might be possible but it took too much time for us). I suggest taking another route and instead creating a database view to join those kind of queries and making a model based off of the database view. Works well for us.

Don’t really get your solution. any examples?

Example… OK. Well this isn’t tested but here’s what you would do:

First take your select statement with a join and make a view in whatever database you’re using (MySQL for instance):




CREATE OR REPLACE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `trip_view` AS

SELECT `t`.`IdDaytrip` AS `t0_c0`, `t`.`Daytrip` AS `t0_c1`,

`t`.`Street` AS `t0_c3`, `t`.`Number` AS `t0_c4`, `t`.`ZipCode` AS `t0_c6`,

`t`.`YouTube` AS `t0_c11`, `t`.`Active` AS `t0_c14`, `t`.`Phone` AS

`t0_c7`, geodistkm(52.360194719, 4.88891601562, rCity.Latitude,

rCity.Longitude) AS Distance, `rCity`.`IdCity` AS `t1_c0`,

`rCity`.`CountryId` AS `t1_c1`, `rCity`.`Province` AS `t1_c2`,

`rCity`.`Municipality` AS `t1_c3`, `rCity`.`City` AS `t1_c4`,

`rCity`.`Deeplink` AS `t1_c5`, `rCity`.`Latitude` AS `t1_c6`,

`rCity`.`Longitude` AS `t1_c7`, `rCity`.`GoogleMatch` AS `t1_c8`,

`rCategory`.`IdCategory` AS `t2_c0`, `rCategory`.`Category` AS `t2_c1`,

`rTag`.`IdTag` AS `t3_c0`, `rTag`.`Tag` AS `t3_c1` FROM `Daytrips` `t` 

LEFT OUTER JOIN `Cities` `rCity` ON (`t`.`CityId`=`rCity`.`IdCity`)  INNER

JOIN `DaytripCategory` `rCategory_rCategory` ON

(`t`.`IdDaytrip`=`rCategory_rCategory`.`DaytripId`) INNER JOIN `Categories`

`rCategory` ON

(`rCategory`.`IdCategory`=`rCategory_rCategory`.`CategoryId`)  INNER JOIN

`DaytripTag` `rTag_rTag` ON (`t`.`IdDaytrip`=`rTag_rTag`.`DaytripId`) INNER

JOIN `Tags` `rTag` ON (`rTag`.`IdTag`=`rTag_rTag`.`TagId`)  WHERE (Active =

1 AND rCategory.IdCategory IN (1,2,3,4,5,6))



NOTE: Those are bad table names, I just copied the select you had above… you’ll want to make the column names a lot nicer and clean up that SQL statement.

Now you should have a view named (in this example at least) “trip_view”. Use gii or whatever to create a model based off of this trip_view (you’ll need database user permissions to show views) and now you can treat it like any other model, only paging and limits will work like normal. Note that in the view I took some stuff out of the WHERE clause because that can be built by yii on the fly. Make sense?

im not sure if this is gonna work. the value for the database function ‘geodistkme’ are depending on a mouse click. the WHERE values are also depending on a selection.

is this an YII bug or am I doing something wrong.

YII guru’s please speak up, is it that hard to join 2 tables and using a WHERE and a LIMIT?

thank you in advanced.

It will work. We do this on a database with over 1 million records and allows people to query over 20 fields. All you have to do is create a database view. If you don’t know about database views you might want to look that up. And yes it really is a pain joining tables like you’re doing and using limit (where should work though with a little work). We have searched for information all over on doing this sort of stuff and every thing I find on these forums people always run in to problems with no solution.

So for your database function ‘geodistkm’ it takes two parameters which come from a mouse click? I don’t get that, a mouse click can’t do anything for a function and your function is using rCity.Latitude and rCity.Longitude which come from a joined table according to your original example… unless my eyes aren’t working too well at the moment. Maybe a simpler example would help?

the first two parameters for the ‘geodistkm’ function are coordinates saved in as $_POST. The user click on a map and the coordinates will be saved in a post en send to the database for calculating the distance bewteen the mouse click on the map en the result found in the database.

after struggling for day i found a solution that works form me.

Yes it is verry simple, just remove the join on the tag table. i only want to show the tagson the page, i dont need them for selecting. so displaying the tags of n item can be done by the eager loading it’s called if i’m right.

joining the category table is neccesary the get the right results using the WHERE condition.

working code:




$categories = implode(", ", $categories);


$criteria = new CDbCriteria(array(

    'condition' => 'Active = 1 AND rCategory_rCategory.CategoryId IN (' . $cats . ')',

    'order' => 'Distance ASC, Priority DESC, RAND()',

    'limit' => 100,

    'with' => array('rCity', 'rCategory'),

));


$daytrips = Daytrip::model()->distance()->findAll($criteria);



If you really had to do the complicated join stuff though the database view would work. You can use the WHERE condition in a database view just like you do a table. I think I might add a section to the cookbook explaining how to do a complicated many_many join setup.

But anyways, glad you got it to work.