CakePHP SQL Operation using 'OR' - php

I am using CakePHP find to retrieve the data. I need to use OR between conditions so i used following query as stated in CakePHP documentation. This works perfectly other times but the problem arises when the field name is same in OR array, Group.arrival_date in this case.
$this->Group->find('all',
array('conditions' => array(
'OR' => array(
'Group.arrival_date' => 'DATE_ADD(CURDATE(), INTERVAL 30 DAY)',
'Group.arrival_date' => 'DATE_ADD(CURDATE(), INTERVAL 7 DAY)'
)
)
));
The SQL it generate is
SELECT `Group`.`id`, `Group`.`rr_no`, `Group`.`package_id`, `Group`.`user_id`,
`Group`.`group_name`, `Group`.`pax`, `Group`.`agent_id`, `Group`.`staff_id`,
`Group`.`arrival_date`, `Group`.`departure_date`, `Group`.`status`, `Group`.`slug`,
`Group`.`book_flight`, `Group`.`allocated_tents`, `Group`.`alert`, `Group`.`alert_seen`
FROM `groups` AS `Group` WHERE `Group`.`arrival_date` = 'DATE_ADD(CURDATE(), INTERVAL 7 DAY)'
It takes the second condition only. For different field name like:
$this->Group->find('all',
array('conditions' => array(
'OR' => array(
'Group.slug' => 'slug1',
'Group.group_name' => 'group1'
)
)
));
The generated SQL is
SELECT `Group`.`id`, `Group`.`rr_no`, `Group`.`package_id`, `Group`.`user_id`,
`Group`.`group_name`, `Group`.`pax`, `Group`.`agent_id`, `Group`.`staff_id`,
`Group`.`arrival_date`, `Group`.`departure_date`, `Group`.`status`, `Group`.`slug`,
`Group`.`book_flight`, `Group`.`allocated_tents`, `Group`.`alert`, `Group`.`alert_seen`
FROM `groups` AS `Group` WHERE ((`Group`.`slug` = 'slug1') OR (`Group`.`group_name` = 'group1'))
Which is as expected. What am i missing in the first find i used? How can i get the above query work? Any help would be greatly appreciated. I am using CakePHP 2.0.

Try:
$this->Group->find('all',
array('conditions' => array(
'OR' => array(
array('Group.arrival_date' => 'DATE_ADD(CURDATE(), INTERVAL 30 DAY)'),
array('Group.arrival_date' => 'DATE_ADD(CURDATE(), INTERVAL 7 DAY)')
)
)
));
Or you could use IN:
$this->Group->find('all',
array('conditions' => array(
'Group.arrival_date' => array('DATE_ADD(CURDATE(), INTERVAL 30 DAY)', 'DATE_ADD(CURDATE(), INTERVAL 7 DAY)')
)
);

For same field, simply put all values you need for OR in an array.
$this->Group->find('all',
array('conditions' => array(
'Group.arrival_date' =>
array('DATE_ADD(CURDATE(), INTERVAL 30 DAY)', 'DATE_ADD(CURDATE(), INTERVAL 7 DAY)' )
)
));

Related

How to get sum of total counts with most recent hourly / daily / weekly / yearly interval in cakephp 3?

I've a table as following-
Now I need to make report of total number of counts in every hour, week, month and year. It may have sum 0 but should be include on the result. For example I need the result as follows-
$hourlyResult = array(
'00:01' => '5',
'00:02' => '9',
'00:03' => '50',
'00:04' => '5',
..............
..............
'00:55' => '95',
'00:56' => '0',
'00:57' => '20',
'00:58' => '33',
'00:59' => '5',
);
$weeklyResult = array(
'SAT' => '500',
'SUN' => '300'
.............
.............
'FRI' => '700'
);
How can I build the query in cakephp 3? I got the following link but can't go so far.
GROUP BY WEEK with SQL
What I've done-
$this->loadModel('Searches');
$searches = $this->Searches
->find('all')
->select(['created', 'count'])
->where('DATE(Searches.created) = DATE_SUB(CURDATE(), INTERVAL 1 DAY)')
->group(WEEK(date))
->hydrate(false)
->toArray();
pr($searches);
Here is how you can do it.
Sum By Year
$query = $this->Searches->find();
$query = $this->Searches
->find()
->select([
'total_count' => $query->func()->sum('count'),
'year' => $query->func()->year(['created' => 'literal'])
])
->group(['year'])
->hydrate(false);
Or
$query = $this->Searches
->find()
->select(['total_count' => 'SUM(count)', 'year' => 'YEAR(created)'])
->group(['year'])
->hydrate(false);
Sum By Day Of Week
$query = $this->Searches->find();
$query = $this->Searches
->find()
->select([
'total_count' => $query->func()->sum('count'),
'day_of_week' => $query->func()->dayOfWeek('created')
])
->group(['day_of_week'])
->hydrate(false);
Or
$query = $this->Searches
->find()
->select(['total_count' => 'SUM(count)', 'day_of_week' => 'DAYOFWEEK(created)'])
->group(['day_of_week'])
->hydrate(false);
The same way you can get total sum by hour or month.
Here you can read about CakePHP > Using SQL Functions and date and time functions in MySQL.

Cakephp get all months records with a single query i.e with single find

I am working on a ecommerce with platform cakephp and using google charts for reports.My requirement is to get all records as per all 12 months, so I have used following code for a single month
Query
SELECT COUNT(*) AS count FROM orderproductmasters AS Orderproductmaster
LEFT JOIN ordermasters AS Ordermaster ON
(Orderproductmaster.ordermaster_id = Ordermaster.id) LEFT JOIN productmasters AS Productmaster ON
(Orderproductmaster.productmaster_id = Productmaster.id)
WHERE Ordermaster.orderstatusmaster_id = 1 AND Month(Orderproductmaster.created) = 8
Code
$this->Orderproductmaster->find('count',
array('conditions'=>array('Ordermaster.orderstatusmaster_id'=>1,'
Month(Orderproductmaster.created)'=>8)));
Since, I need records as per Jan, feb,march and all 12 months...,so for 12 months I am using following code
for($i=1;$i<13;$i++)
{
$orderproductmasters[$i] = $this->Orderproductmaster->find('count',
array('conditions'=>array('Ordermaster.orderstatusmaster_id'=>1,
'Month(Orderproductmaster.created)'=>$i)));
}
So question might be silly, but is it possible to get all months record without using for loop i.e, within a single query.
Thanks in advance
I think , your need can be fulfilled by using cursors in stored procedure. And then using stored procedure to cake-php.
Example on db side is here
$options = array();
$options['fields'] = array('COUNT(Orderproductmaster.id)');
$options['conditions'] = array('Ordermaster.orderstatusmaster_id = 1',
'Month(Orderproductmaster.created) BETWEEN 1 AND 12');
$options['joins'] = array(
array(
'table' => 'ordermasters',
'alias' => 'Ordermaster',
'type' => 'left',
'conditions' => array(
'Orderproductmaster.ordermaster_id = Ordermaster.id'
)
),
array(
'table' => 'productmasters',
'alias' => 'Productmaster',
'type' => 'left',
'conditions' => array(
'Orderproductmaster.productmaster_id = Productmaster.id'
)
)
);
$options['group'] => array('Month(Orderproductmaster.created)');
$this->Orderproductmaster->find('all',$options);
What About something like:
$this->Orderproductmaster->find('count',
array(
'fields'=>'DISTINCT(Month(Orderproductmaster.created)),
'conditions'=>array('Ordermaster.orderstatusmaster_id'=>1,'
Month(Orderproductmaster.created)'=>8)));

How can i select records from two tables in cake php(cake 2)

I am new to cake php . i have two tables
ce_landing
ce_stat
structure is
ce_stat
id keyword click
1 keyword1 24
2 keyword2 2
3 keyword3 6
ce_landing
id page_keyword
1 keyword1,check,keyword3
2 keyword2,usa,alphanumeric
i want to fetch all the records ce_landing.page_keyword is present in ce_stat.keyword. I am using this in my cake php model
public $hasMany = array(
'Stat' => array(
'className' => 'Stat',
'foreignKey' => 'keywor',
'dependent' => false,
'conditions' => array('Stat.keyword LIKE' => '%Landing.page_keywords%'),
'group' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
but this is generated sql query like
SQL Query: SELECT Stat.id, Stat.customer_id, Stat.account,
Stat.campaign_id, Stat.campaign, Stat.keyword,
Stat.ad_grp_id, Stat.ad_grp, Stat.impressions,
Stat.clicks, Stat.cost, Stat.qualityScore,
Stat.keywordState, Stat.date_from, Stat.date_to,
Stat.user_id, Stat.created, Stat.modified, Stat.keywor
FROM EB_adwords.ce_stats AS Stat WHERE Stat.keyword LIKE
'%Landing.page_keywords%' AND Stat.keyword =
('559f479a-82ac-4e3d-8c24-19b5c0a8011f')
so it returns null data because of AND Stat.keyword =('559f479a-82ac-4e3d-8c24-19b5c0a8011f') conditions.
Update
what i want to get all the records from ce_landing with total clicks according to keywords present . i.e for record 1 in ce_landing. i'll get the result
id page_keyword clicks
1 keyword1,check,keyword3 30
2 keyword2,usa,alphanumeric 2
You needs a SQL statement equivalent to:
SELECT ce_landing.id, ce_landing.page_keyword, SUM(ce_stat.click) AS total_clicks
FROM ce_landing
LEFT JOIN ce_stat
ON FIND_IN_SET(keyword,page_keyword)>0
GROUP BY ce_landing.id, ce_landing.page_keyword;
which does not easily translate to Cakephp's find method. Just use the query method to implement.
$this->Landing->query("SELECT Landing.id, Landing.page_keyword, SUM(ce_stat.click) AS total_clicks
FROM ce_landing AS Landing
LEFT JOIN ce_stat
ON FIND_IN_SET(keyword,page_keyword)>0
GROUP BY Landing.id, Landing.page_keyword;");

How to do a timediff or datediff query in CakePHP

I want to run this query:
SELECT * FROM `foobar`
where
TIMESTAMPDIFF(MINUTE,request_time,NOW()) < 15
I have tried:
$this->find('first',
array('conditions' =>
array('username' => $v['User']['username']),
'TIMESTAMPDIFF(MINUTE,request_time,NOW()) < ' => 15));
You have to place the SQL fragment inside of the conditions array, currently it's placed outside and thus it's being ignored.
$this->find('first', array
(
'conditions' => array
(
'username' => $v['User']['username'],
// this is where it needs to go
'TIMESTAMPDIFF(MINUTE, request_time, NOW()) < ' => 15
)
// this is where it was before
));
That will result in a query similar to this:
SELECT
`Model`.`username`, ...
FROM
`db`.`model` AS `Model`
WHERE
`username` = 'whatever'
AND
TIMESTAMPDIFF(MINUTE, request_time, NOW()) < 15
LIMIT 1
By default CakePHP will include all fields in the SELECT statement.
Obviously if you want the query to use only the TIMESTAMPDIFF condition as in your example, then you have to drop 'username' => $v['User']['username'].

cakePHP complex find query

how do I build a find() query in cakePHP using these conditions:
Find where
MyModel.x = 1 and MyModel.y = 2 OR
MyModel.x = 1 and MyModel.y value does not exist (or is equal to empty string)
Can somebody tell me how I can go about building such find query?
I'm gonna give you some pointers, but you need to try to do this as it's very basic and it's always good to practice.
A basic find in cake is in the form of
$this->ModelName->find('all');
This in its default form does a SELECT * from model_names (convention is to have singular ModelName for plural table name - model_names)
To add conditions:
$this->ModelName->find('all', array('conditions' => array('ModelName.x' => 1));
To add AND conditions
$this->ModelName->find('all', array('conditions' => array(
'ModelName.x' => 1, 'ModelName.y' => 2
));
To add OR conditions
$this->ModelName->find('all', array('conditions' => array(
'OR' => array(
'ModelName.x' => 1, 'ModelName.y' => 2
)
));
To combine both
$this->ModelName->find('all', array('conditions' => array(
'ModelName.y is not' => null,
'OR' => array(
'ModelName.x' => 1, 'ModelName.y' => 2
)
));
// where y is not null and (x = 1 or y = 2)
http://book.cakephp.org/1.3/view/1030/Complex-Find-Conditions
(btw I'm sure there will be users giving you the exact answers, so just take my answer for your reference :) )
$this->MyModel->find('all', array('conditions' => array(
'OR' => array(
array(
'MyModel.x' => 1,
'MyModel.y' => 1
),
array(
'MyModle.x' => 1,
'OR' => array(
array('MyModel.y' => NULL),
array('MyModel.y' => '')
)
)
)
)));

Categories