Laravel how to match 2 values with one field - mysql

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);

Related

Yii2 getting columns name from SQL command when result == null

If you get the following code :
$DBConnection =
CreateNewDBConnection(Yii::$app->get('db_cdh'),$aDatabaseName);
$DBConnection->open();
$command = $DBConnection->createCommand($aQuery);
$queryres = $command->queryAll();
If there is result from the query, I get an array, like this
Array
(
[0] => Array
(
[name] => 2.6.084.545
[xdim+2] => 70
)
[1] => Array
(
[name] => 2.5.102.030
[xdim+2] => 60
)
[2] => Array
(
[name] => 2.5.141.560
[xdim+2] => 80
)
)
But if the result of the query is empty, i get an empty array.
How is it possible to get the columns name ?
The reason why I'm asking this, it's because I'm asking queries to multiple DBs and some have results (1 or more lines) and otherd not. The system almost works, but the grid view parse only the first line to find the columns to display. So depending on the order result across the multiple DB, the grid view display the columns or not, depending what come first ....
Any help welcome.
You can take the column names using yii\db\TableSchema and use them afterwards:
$columns = [];
if (empty($queryres)) {
$columns = $DBConnection->getTableSchema('your_table_name')->getColumnNames();
}

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']);

Cakephp find joining two columns

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';

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 if condition in query can't get tablename from mysql_field_table

This query works:
SELECT Article.id,
Article.post_time,
Article.post_locked,
Article.comments_locked, Article.title,
IF(CHAR_LENGTH(Article.content)>2000,
RPAD(LEFT(Article.content,2000),2003,'.'),
Article.content) as content,
Article.tags, Category.*,
User.id, User.user_name,
Comment.comment_count
FROM `articles` as `Article`
LEFT JOIN `categories` as `Category` ON `Article`.`category_id` = `Category`.`id`
LEFT JOIN `users` as `User` ON `Article`.`user_id` = `User`.`id`
LEFT OUTER JOIN (SELECT article_id, count(*) comment_count FROM `comments`) as `Comment` ON `Article`.id = `Comment`.article_id
WHERE '1'='1'
ORDER BY `Article`.`id` DESC
But when I loop through the resultset to assign the table name along with the field using 'mysql_field_table', the 'content' returns a table name of nothing, while all others have their correct table:
Array (
[0] => Article
[1] => Article
[2] => Article
[3] => Article
[4] => Article
[5] =>
[6] => Article
[7] => Category
[8] => Category
[9] => User
[10] => User
[11] => Comment )
using
for ($i = 0; $i < $numOfFields; ++$i) {
array_push($table,mysql_field_table($this->_result, $i));
array_push($field,mysql_field_name($this->_result, $i));
}
Anyone ever try to do this? Have a solution? I want to return less data from my DB in my query. Or is it less intensive (on mysql, memory, cpu) to simply select all content and truncate the content via PHP? I thought returning less from DB would be better.
Thanks a bunch!!
Peace.
EDIT
to clear up, this is the result, you will see why it isnt what I want:
Array (
[0] => Array (
[Article] => Array (
[id] => 8
[post_time] => 1278606312
[post_locked] => 0
[comments_locked] => 0
[title] => Article 8
[tags] => test )
[] => Array (
[content] => my content for Article )
[Category] => Array (
[id] => 2
[name] => cat2 )
[User] => Array (
[id] => 3
[user_name] => user3 )
[Comment] => Array (
[comment_count] => 1 )
)
[1] => Array (
[Article] => Array (
[id] => 7
etc...
In order to use characters beyond the English alphabet and spaces in a column alias, the standard SQL means requires using double quotes (though MySQL supports using backticks IE: "`" too):
...,
IF(CHAR_LENGTH(Article.content)>2000,
RPAD(LEFT(Article.content,2000),2003,'.'),
Article.content) AS "Article.content",
...
no you cant use a as [tablename].[columnname]-like format for custom column names.
It would be weird anyway if it would work, because how can content be defined as 'Article.content' if it's not really part of the Article table dataset.
Just select the columns you need and join where needed.
But what's WHERE '1' = '1' doing in there? that will just evaluate to true as it is a boolean expression, but it won't affect your resultset.
But when I loop through the resultset
to assign the table name along with
the field using 'mysql_field_table',
the 'content' returns a table name of
nothing, while all others have their
correct table
Once you've done that magic on Article.content, to create the content field, it no longer belongs to the Article table. Rather, it belongs to the result set of that query. I believe that's the explanation for having no table associated with that field.
Imagine a GROUP BY query, with something like COUNT(*) as number. 'number' doesn't belong to any table.
If you really need the ability to know that the column had a particular source, could you have a view on top of Article which does this manipulation to content? Then the source would appear to be the view? Unfortunately, MySQL doesn't support declared computed columns in tables, that might also be useful to you in this case.
while ($row = mysql_fetch_row($this->_result)) {
$prev_table;
for ($i = 0;$i < $numOfFields; ++$i) {
if ($table[$i] == "") {
$tempResults[$prev_table][$field[$i]] = $row[$i];
}else {
$tempResults[$table[$i]][$field[$i]] = $row[$i];
}
$prev_table = $table[$i];
}
}
Oh well, mysql couldnt do what I wanted. I added the prev_table to take the one before ;)
Thanks to everyone for the help.