Cakephp find joining two columns - mysql

I have a BD that contains people with day and month fields, like so:
person1 (day = 5; month = 3)
person2 (day = 2; month = 12)
I have to perform a find between 2 dates, for example, I need all people between 01/03 and 01/06 (day/month) but I don't know how to perform that.
I tried using separate conditions, like this:
$conditions['People.day >='] = dayA;
$conditions['People.month >='] = monthA;
$conditions['People.day <='] = dayB;
$conditions['People.month <='] = monthB;
But, that's not correct because it finds day and month, I mean, it finds People between monthA and monthB and People between dayA and dayB, instead, what I need is people between dayA/monthA and dayB/monthB
I suppose I must do some kind of a JOIN, but I'm lost here, I looked some information but I don't know where to start.
updated info:
ok, I'm using this
Array
(
[People.month_day BETWEEN ? AND ?] => Array
(
[0] => 01/02
[1] => 28/02
)
)
but I get people like this:
1/1
2/1
10/1
11/1
12/1
13/1
20/1
21/1
1/2
what's wrong? do you need more code? I'm using this to retrieve results:
A paginate:
public $paginate = array('People'=>array(
'limit' => 16,
'order' => 'People.month, People.day ASC'
));

In your People model
public $virtualFields = array(
'month_day' => 'CONCAT(People.month, "-", People.day)'
// 'month_day' => 'CONCAT(People.day, "/", People.month)'
);
then add in your controller
$options = array(
'conditions' => array(
'Post.month_day BETWEEN ? AND ?' => array('01-03','01-06')
// 'Post.month_day BETWEEN ? AND ?' => array('03/01','06/01')
)
);
$posts = $this->Post->find('all',$options);

It would be best to alter your table. Use DATE field and your SQL query would be:
SELECT *
FROM dbname.People
WHERE People.date BETWEEN '1999-03-01' AND '1999-06-01';

Related

How to use AND and OR in MySQL query?

I want to get those records whose date_last_copied field is empty or less than the current date. I tried this, but it did not give me the desired result:
$tasks = $this->Control->query("
SELECT *
FROM
`controls`
WHERE
`owner_id` = ".$user_id."
AND `control_frequency_id` = ".CONTROL_FREQUENCY_DAILY."
OR `date_last_copied` = ''
OR `date_last_copied` < ". strtotime(Date('Y-m-d'))."
");
Current query looks something like this, I think. That is, find the records with the correct owner_id and frequency_id, where the date_last_copied is null or less than a certain date. Is that logic correct?
SELECT *
FROM controls
WHERE owner_id = ::owner_id::
AND control_frequency_id = ::frequency_id::
AND (
date_last_copied IS NULL
OR date_last_copied < ::date::
)
But we should really be using the CakePHP query builder, rather than running raw SQL. This article gives some details. If I were to take a stab at a solution, we'd want something like the following. But we ideally want someone from the CakePHP community to chime in here. EDIT: Note that this seems to be for CakePHP 3.0, only.
// Build the query
$query = TableRegistry::get('controls')
->find()
->where([
'owner_id' => $ownerId,
'control_frequency_id' => $frequencyId,
'OR' => [
['date_last_copied IS' => null],
['date_last_copied <' => $date]
]
]);
// To make sure the query is what we wanted
debug($query);
// To get all the results of the query
foreach ($query as $control) {
. . .
}
I'm suggesting this, rather than the raw SQL string you have above, because:
We can now leverage the ORM model of CakePHP.
We don't have to worry about SQL injection, which you're currently vulnerable to.
EDIT: OK, this is a guess at the syntax applicable for CakePHP 2.0... YMMV
$controls = $this->controls->find('all', [
'conditions' => [
'owner_id' => $ownerId,
'control_frequency_id' => $frequencyId,
'OR' => [
['date_last_copied IS' => null],
['date_last_copied <' => $date]
]
]
];
Otherwise, we just use the raw query as a prepared statement:
$result = $this->getDataSource()->fetchAll("
SELECT *
FROM controls
WHERE owner_id = ?
AND control_frequency_id = ?
AND (
date_last_copied IS NULL
OR date_last_copied < ?
)",
[$ownerId, $frequencyId, $date]
);
Not sure about your whole logic but your final query statement should be something like:
SELECT * FROM `controls` WHERE (`owner_id` = <some owner_id>)
AND (`control_frequency_id` = <some id value>)
AND (`date_last_copied` = '' OR
`date_last_copied` IS NULL OR
`date_last_copied` < CURDATE() )
Use parentheses carefully to match your logic.
Always specify the version of cakePHP you are using for your App.
This query should work fine in CakePHP 3.0 for SQL AND and OR.
$query = ModelName>find()
->where(['colunm' => 'condition'])
->orWhere(['colunm' => 'otherCondition'])
->andWhere([
'colunm' => 'anotherContion',
'view_count >' => 10
])
->orWhere(['colunm' => 'moreConditions']);

Laravel how to match 2 values with one field

Currently I am facing problem that I am using orWhere to get the correct result but not getting the exact result. I want to get result where my field contain only Paid and Flexible
E.g
Status
Paid
Paid
Flexible
Paid
Paid
Flexible
But with this query I am also getting UnPaid but I don't want UnPaid result
$orders = Order::with('orderfiles','orderStatus','orderDelivery','flexibleDelivery')->whereHas('payment', function ($query) {
$query->where("status","=",'Paid')->orwhere('status' ,'=', 'Flexible');
})->whereBetween("tbl_orders.order_date", $range)->where('domain_id','=',$domain_id)->orderBy('order_date','asc')->paginate();
return View('admin.all_orders')
->with('orders',$orders)->with('title','Results - Paid and Flexible Orders')->with('logoNum',$domain_id);
Sql
Array
(
[0] => select count(*) as aggregate from `tbl_orders` where (select count(*) from `tbl_payments` where `tbl_payments`.`order_id` = `tbl_orders`.`order_id` and `status` = ? or `status` = ?) >= 1 and `tbl_orders`.`order_date` between ? and ? and `domain_id` = ?
[1] => Array
(
[0] => Paid
[1] => Flexible
[2] => 2015-01-01
[3] => 2015-05-31
[4] => 18
)
[2] => 7233.41
[3] => mysql
)
I know you’ve already accepted an answer, but it’s really not the best way. You could use Laravel’s whereIn query method:
$query->whereIn('status', ['Paid', 'Flexible']);
The first parameter is the column name, and the second is an array of values you want to match.
Use Db::RAW
for more help read: http://laravel.com/docs/4.2/queries
$orders = Order::with('orderfiles','orderStatus','orderDelivery','flexibleDelivery')->whereHas('payment', function ($query) {
$query->where(DB::raw('(`status` = \'Paid\') OR (`status` = \'Flexible\')'));
})->whereBetween("tbl_orders.order_date", $range)->where('domain_id','=',$domain_id)->orderBy('order_date','asc')->paginate();
return View('admin.all_orders')
->with('orders',$orders)->with('title','Results - Paid and Flexible Orders')->with('logoNum',$domain_id);

Mysql returns only the first result

I have this query for a search form:
// General Query
$conditions = array(
'editore LIKE' => "%$e%",
'titolo LIKE' => "%$t%"
);
Now, if the user chooses fill some field (eg author, year, etc), I have:
if (isset($menu)&&$menu!='')
$conditions[]=array('classe LIKE' => "%$menu%");
Or:
if ($anno&&$anno2)
$conditions[] = array('anno BETWEEN ? AND ?' => array($anno,$anno2));
If the user chooses some tags for the book, I have:
$query_t = $CdBibliotem->query("SELECT codiceBiblio FROM cd_bibliotem WHERE codiceTematica IN (".implode(',', $fields).")");
$query_t = Set::classicExtract($query_t,'{n}.cd_bibliotem.codiceBiblio');
$tot=implode(',', $query_t);
$conditions[]=array('codiceBiblio IN (?)'=> "$tot");
This should work, but instead I don't know why, it gives me only the first record.
This is an example of debug a final query, where the user selects only 1 tag, and leaves the others fields empty:
Array (
[editore LIKE] => %%
[titolo LIKE] => %%
[0] => Array
(
[autori LIKE] => %%
)
[1] => Array
(
[codiceBiblio IN (?)] => 118729,118656,118645,118554,118534,118533,118532,118531,118530,118529,118528,118527,118526,118121,117632,117515,117040,116562,115851,115787,114613,114612,113545,113385,113142
) )
In this case, it gives me all the details of the first book (with id=118729), while it should gives me the details of all that books.

CakePHP has and belongs to many conditions with NOT EXISTS

$conditions = Array
(
[table] => products_pages
[alias] => ProductsPage
[type] => inner
[foreignKey] =>
[conditions] => Array
(
[0] => ProductsPage.product_id = Product.id
)
)
I'm trying to set up NOT EXISTS conditions, like the following SQL statement:
SELECT * FROM products_pages,products
WHERE NOT EXISTS (SELECT id
from products_pages
where products_pages.product_id = products.id)
So basically select any product that doesn't exist in the products_pages table.
What is the proper way to format that SQL statement for CakePHP and replace it here:
[conditions] => Array
(
[0] => (What's the proper way to insert above SQL here?
)
Would really appreciate your help guys, I've been trying to figure this out for about 5 hours with no luck. Thanks!
You can always use query if you don't find the way to do it with CakePHP:
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-query
In this case security wouldn't be compromised as you are not using any input.
Anyway, something simple would be just to do it in more than one step:
//selecting the products in the productcs_pages table
$productsWithPages = /* query to get them*/
//getting an array of IDs
$productsWidthPagesIds = Hash::extract($productsWithPages, '{n}.Product.id');
//doing the NOT IN to select products without pages
$productsWithoutPages= $this->Product->find('all',
array('conditions' =>
array( 'NOT' => array('Product.id' => $productsWidthPagesIds )
)
);

MySQL short but highly complex results problem w/ two variations of search

My search is working as expected, but I have an added factor which I cannot sort out.
This is the breakdown of what I need to achieve in one query:
$ApplicantAge BETWEEN Age.Min_Age AND Age.Max_age.
NOT 'PlanDetail.company_id' => '27'
$PsSpouseAge BETWEEN Age.Min_Age AND Age.Max_age.
WHERE 'PlanDetail.company_id' => '27'
So as you can see with $ApplicantAge matches, I need to get all records that do not have company_id = 27, and then where $PsSpouseAge matches, only get records with the company_id = 27.
So all records merge together... So essentially there are two queries on the same data at the same time and then all records merged into the result.
As I said, my search is working fine, but I need to integrate this in and sort out the MySQL which I am having 0 luck with.
I've tried many AND / OR AND AND options, and the closest I can get is overwriting the first part of the query with the second part which of course does no good.
What I am trying now:
'conditions' => array(
'AND' => array(
array($ApplicantAge . ' BETWEEN Age.Min_Age AND Age.Max_age'),
'AND' => array('Zips.title' => $Zip),
'AND' => array('Applicant.amount' => array($comboType, $memberCount)),
'NOT' => array('PlanDetail.company_id' => '27'),
array('OR' =>
array($PsSpouseAge . ' BETWEEN Age.Min_Age AND Age.Max_age'),
'AND' => array('Zips.title' => $Zip),
'AND' => array('Applicant.amount' => array($comboType, $memberCount)),
'AND' => array('PlanDetail.company_id' => '27'))
)),
And my SQL output is so:
WHERE ((19 BETWEEN `Age`.`Min_Age` AND `Age`.`Max_age`) AND (`Applicant`.`amount` IN ('as', '2')) AND (NOT (`PlanDetail`.`company_id` = 27)) AND (((21 BETWEEN `Age`.`Min_Age` AND `Age`.`Max_age`) AND (`PlanDetail`.`company_id` = 27))))
It's a bit difficult to understand what you're looking for, but perhaps you want this?
([$ApplicantAge] BETWEEN Age.Min_Age AND Age.Max_age AND PlanDetail.company_id != 27) OR ([$PsSpouseAge] BETWEEN Age.Min_Age AND Age.Max_age AND PlanDetail.company_id = 27)
The simple answer to your question is just use UNION something like:
Select 'Applicant', Age
Where $ApplicantAge BETWEEN Age.Min_Age AND Age.Max_age. NOT 'PlanDetail.company_id' <> '27'
Union
Select 'Spouse', Age
Where $PsSpouseAge BETWEEN Age.Min_Age AND Age.Max_age. WHERE 'PlanDetail.company_id' = '27'
However I think we are missing some important details on the relationship between applicant and Spouse.