I am running a Mysql query in CakePHP but it is not outputting any result though no error is displayed.
Mysql query is this:
SELECT `isbn`, `title`, `author_name` FROM `books` WHERE `author_name` = 'William Rice' AND `title` LIKE '%Course%' ORDER BY `title` ASC
and it outputs results.
And I have written this in CakePHP find function:
$books = $this->Book->find('all', array('fields'=>array('Book.isbn', 'Book.title', 'Book.author_name'),
'conditions'=>array('Book.author_name'=>'William Rice',
'AND'=>array('Book.title'=>'LIKE %Course%')),
'order'=>'Book.title ASC',
));
But the query doesn't run. Is AND condition specified like this? Please have a look at it and tell me where is it wrong. Thanks.
Do not use AND array:
You have to change your query as given below:
$books = $this->Book->find('all',
array('fields'=>array('Book.isbn', 'Book.title', 'Book.author_name'),
'conditions'=>array('Book.author_name'=>'William Rice',
'Book.title LIKE'=>'%Course%'),
'order'=>'Book.title ASC'
));
$books = $this->Book->find('all', array(
'fields' => array('Book.isbn', 'Book.title', 'Book.author_name'),
'conditions' => array(
'Book.author_name'=>'William Rice',
'Book.title LIKE'=>'%Course%'
),
'order'=>'Book.title ASC',
));
You have done only one mistake , Remove 'AND' from your query, after removing 'AND' your query will be like below query.
$books = $this->Book->find('all', array(
'fields' => array('Book.isbn', 'Book.title', 'Book.author_name'),
'conditions' => array(
'Book.author_name'=>'William Rice',
'Book.title LIKE'=>'%Course%'
),
'order'=>'Book.title ASC',
)
);
Related
I am using subquery for id field.
$db = $this->AccountRequest->getDataSource();
$subQuery = $db->buildStatement(
array(
'fields' => array('MAX(id)'),
'table' => $db->fullTableName($this->AccountRequest),
'alias' => 'MaxRecord',
'limit' => null,
'offset' => null,
'order' => null,
'group' => array("user_id")
),
$this->AccountRequest
);
$searching_parameters = array(
#"AccountRequest.id IN " => "(SELECT MAX( id ) FROM `account_requests` GROUP BY user_id)"
"AccountRequest.id IN " => "(".$subQuery.")"
);
$this->Paginator->settings = array(
#'fields' => array('AccountRequest.*'),
'conditions' => $searching_parameters,
'limit' => $limit,
'page' => $page_number,
#'group' => array("AccountRequest.user_id"),
'order' => array(
'AccountRequest.id' => 'DESC'
)
);
$data = $this->Paginator->paginate('AccountRequest');
This structure is producing a query is:
SELECT
`AccountRequest`.`id`,
`AccountRequest`.`user_id`,
`AccountRequest`.`email`,
`AccountRequest`.`emailchange`,
`AccountRequest`.`email_previously_changed`,
`AccountRequest`.`first_name`,
`AccountRequest`.`first_namechange`,
`AccountRequest`.`f_name_previously_changed`,
`AccountRequest`.`last_name`,
`AccountRequest`.`last_namechange`,
`AccountRequest`.`l_name_previously_changed`,
`AccountRequest`.`reason`,
`AccountRequest`.`status`,
`AccountRequest`.`created`,
`AccountRequest`.`modified`
FROM
`syonserv_meetauto`.`account_requests` AS `AccountRequest`
WHERE
`AccountRequest`.`id` IN '(SELECT MAX(id) FROM `syonserv_meetauto`.`account_requests` AS `MaxRecord` WHERE 1 = 1 GROUP BY user_id)'
ORDER BY
`AccountRequest`.`id` DESC
LIMIT 25
In the subquery, its add an extra single quote so it's producing an error.
So, How can I remove these single quotes from this subquery?
Thanks
What are you trying to achieve with the sub query?
The MAX(id) just means it will pull the id with the largest value AKA the most recent insert. The sub query is completely redundant when you can just ORDER BY id DESC.
using MAX() will return only one record, if this is what you want to achieve you can replicate by adding LIMIT 1
If the sub query is just an example and is meant to be from another table I would just run the query that gets the most recent id before running the main query. Getting the last inserted id in a separate query is very quick and I cant see much of a performance loss. I think it will result in cleaner code that`s easier to follow to.
edit 1: From the comments it sounds like all your trying to get is a particular users latest account_requests.
You dont need the sub query at all. My query below will get the most recent account record for the user id you choose.
$this->Paginator->settings = array(
'fields' => array('AccountRequest.*'),
'conditions' => array(
'AccountRequest.user_id' => $userID // you need to set the $userID
)
'page' => $page_number,
'order' => array(
'AccountRequest.id DESC' //shows most recent first
),
'limit' => 1 // set however many you want the maximum to be
);
The other thing you cold be meaning is to get multiple entries from multiple users and display them in order of user first and then the order of recent to old for that user. MYSQL lets you order by more than one field, in that case try:
$this->Paginator->settings = array(
'conditions' => array(
'AccountRequest.user_id' => $userID // you need to set the $userID
)
'page' => $page_number,
'order' => array(
'AccountRequest.user_id', //order by the users first
'AccountRequest.id DESC' //then order there requests by recent to old
)
);
If the example data you have added into the question is irrelevant and you are only concerned about how to do nested subqueries it has already been answered here
CakePHP nesting two select queries
However I still think based on the data in the question you can avoid using a nested query.
How can I transform the SQL statement into the CakePHP Code? I am able to get the group by result. But how can I add the inner Select Count(*) statement?
I've updated the code under "Revised" However, I am getting this error. Parse error: syntax error, unexpected 'INCOMPLETE' (T_STRING), expecting ')'. I am sure I check my open and close brackets.
SQL Statement below
SELECT
`id` ,
`mtpToken` ,
`mtpCreator_id` ,
`school_id` ,
`user_id` ,
`mtpStatus` ,
`created` ,
`modified` ,
(
(SELECT COUNT( * ) FROM mtpScreenings
WHERE (mtpStatus = 'INCOMPLETE' OR mtpStatus = 'HALFWAY') AND mtpToken = `mtpToken` )
) AS `mainStatus`
FROM `mtpScreenings` WHERE `mtpScreenings`.`school_id` = 15 GROUP BY `mtpToken`
CakePHP Code below
$setting = $this->paginate = array(
conditions' => array('MtpScreening.school_id' => 15),
'recursive' => -1,
'fields' => array('MtpScreening.field1'),
'group' => array('MtpScreening.mtpToken'),
'limit' => 1000
);
Revised
$setting = $this->paginate = array(
conditions' => array('MtpScreening.school_id' => 15),
'recursive' => -1,
'fields' => array('SELECT COUNT(*) FROM mtpScreenings
WHERE (mtpStatus = "INCOMPLETE" OR mtpStatus = "HALFWAY") AND mtpToken = `mtpToken`
) AS mainStatus'),
'group' => array('MtpScreening.mtpToken'),
'limit' => 1000
);
Virtual Field
Code example of virtual field:
public $virtualFields = array(
'count' => "SELECT COUNT( * ) FROM MtpScreening
WHERE (MtpScreening.mtpStatus = 'INCOMPLETE' OR MtpScreening.mtpStatus = 'HALFWAY') AND MtpScreening.mtpToken = 'mtpToken'"
);
This code will produce virtual field:
$this->find('all', array(
'fields'=>array(
'MtpScreening.id',
'MtpScreening.mtpToken',
'MtpScreening.mtpCreator_id',
'MtpScreening.school_id',
'MtpScreening.count'/*virtual field*/
)
)
);
Pagination and virtual fields
Since virtual fields behave much like regular fields when doing
find’s, Controller::paginate() will be
able to sort by virtual fields too.
Please help me to retrieve data from a table by multiple condition in Cakephp
I have one table name: article; I have tried to retrieve data with the code below
I want to get specific id as given in the parameter; article_price > 0 and article_status > 1
public function getArticle($artID = ''){
return $this->find('all', array(
'condition' => array(
'article_id =' => $artID,
'article_price' => '> 0',
'article_status = ' => '1'),
'order' => 'article_id DESC'
));
}
// the out put was selected all data without condition that I want.
What was the problem with my code?
What I found out is I print: echo $this->element ('sql_dump'); and I got the following sql statement:
SELECT `article`.`article_id`, `article`.`name`, `article`.`article_price`, `article`.`article_status` FROM `db_1stcakephp`.`article` AS `article` WHERE 1 = 1 ORDER BY `article_id` DESC
Please help me.
Thank!
If your model name is Article:
public function getArticle($art_id) {
return $this->find('first', array(
'conditions' => array(
'Article.article_id' => $art_id,
'Article.article_price >' => 0,
'Article.article_status >' => 1,
),
));
}
Using 'Model.field' syntax is optional, until your models have relationship and have the same names - for example Article.status and Author.status.
Moving comparison sign into array's key part allows you to do:
'Article.price >' => $minPrice,
'Article.price <=' => $maxPrice,
And I didn't really notice typo in 'conditions'.
In my CakePHP model I'm trying to get some data from my table.
I tried using DISTINCT but it seems like using DISTINCT doesn't change the query results.
I can see many rows that has the same nick
with 'DISTINCT Mytable.nick'
$this->Mytable->find('all',
array(
'fields'=> array(
'DISTINCT Mytable.nick',
'Mytable.age', 'Mytable.location',
),
'conditions' => array('Mytable.id >=' => 1, 'Mytable.id <=' => 100),
'order' => array('Mytable.id DESC')
));
with 'group Mytable.nick'
$this->Mytable->find('all',
array(
'fields'=> array(
'Mytable.nick',
'Mytable.age', 'Mytable.location',
),
'conditions' => array('Mytable.id >=' => 1, 'Mytable.id <=' => 100),
'group' => 'Mytable.nick',
'order' => array('Mytable.id DESC')
));
with 'Mytable.nick'
$this->Mytable->find('all',
array(
'fields'=> array(
'Mytable.nick',
'Mytable.age', 'Mytable.location',
),
'conditions' => array('Mytable.id >=' => 1, 'Mytable.id <=' => 100),
'order' => array('Mytable.id DESC')
));
Edit: It seems like even CakePHP 2.1 can't use DISTINCT option. When I tried "GROUP BY" it solved my issue. But as you can see from my query I need to order results with Mytable.id descended. When I use GROUP BY, when Mysql finds relevant row, it doesn't take others. For example.
id=1, nick=mike, age=38, location=uk
id=2, nick=albert, age=60, location=usa
id=3, nick=ash, age=42, location=uk
id=4, nick=albert, age=60, location=new_zelland
When I use group Mytable.nick, I don't see 4th row in my results, I see 2nd row. Because when mysql saw "albert" second time, it doesn't put it into my results. But I need latest "albert" result. Is it not possible?
Edit2: It seems like order by/group by conflict is a common problem. I found some tips in this question. But it gives solution for native Mysql queries. I need a solution for CakePHP type queries.
Not clear on why you want to group by nick and order by id. Do you intend to use an aggregate function like COUNT() to see how many occurrences of the same nick there are? In short you overall goal still is not clear to me. Might be worth being aware of the HAVING MySQL keyword.
Updated: Ok, that makes more sense. So you need to use a sub select on the condition or perhaps express that as a join. I'll try and show an example using the sub select in the WHERE clause.
/* select last occurrence for each nick (if you need one for each location )*/
SELECT nick, age, location
FROM myTable t1
WHERE id =
(SELECT MAX(id)
FROM myTable t1
WHERE t1.nick = t2.nick);
Would think something like this would work:
$this->Mytable->find('all',
array(
'fields'=> array(
'Mytable.nick',
'Mytable.age', 'Mytable.location',
),
'conditions' => array('Mytable.id =' => '(SELECT MAX(id) FROM myTable t2 WHERE myTable.nick = t2.nick)', 'Mytable.id <=' => 100)
));
so I can look for concrete values by doing
$recordset= Model::find('all', array(
'conditions' => array(
'condition' => $somevalue
)
))
however, what do I do if I want to match on a partial value?
right now, I've resorted to writing the query myself, a la:
$abc = Connections::get('default')->
read('SELECT * FROM myTable WHERE condition LIKE "%partial string%"');
Here's how I do an SQL 'like' search:
$user = User::find('all', array(
'conditions' => array(
'first_name' => array('like' => '%yeun%'))
)
);
'like' being the keyword, there.
That would generate a query like:
SELECT * FROM `users` AS `Users` WHERE (`first_name` like '%yeun%');
Hope that helps.