Rose DB subselect (nested query ) on select - mysql

I am trying to run a query, that has a subselect in it. I have set up the Manager method, and everything works fine. The only problem is i dont know how to proceed with this query :
SELECT * FROM tableA WHERE
name = 'Me' AND
class='Tester' AND
( ( Department IN ( SELECT Department FROM
tableB WHERE
leader = 'Joe')
OR
Leader in ('','all') )
);
Its important to remember that tableA and tableB are 2 different tables . As of now i have reached this query :
my #leader = ('','all');
DB::tableA::Manager->get_tableA ( with_object => ['tableB'] ,
query => [ name => 'Me',
class => 'Tester',
OR => [
leader => \#leader,
Department => [*** this is
where i have to make the sub select.
Dont know how though **** ]
]
],
debug => 1);
please help so that i can add that sub query to this main query
Thanks in advance

You can use the clauses function to include arbitrary clauses in the query's WHERE portion.
It would look like this.
DB::tableA::Manager->get_tableA ( with_object => ['tableB'] ,
query => [
name => 'Me',
class => 'Tester',
],
clauses => ["( Department IN ( SELECT Department FROM tableB WHERE leader = 'Joe' ) OR Leader in ('','all') )"
);
CPAN: Rose::DB::Object::QueryBuilder, Functions

Related

mysql - select result of two conditionals for the same table in one query

I am struggling to get correct results with this. I want to test if both, or either, exist. In results table, 'michael' exists while 'mike' does not.
$stmt = $dbnet->prepare("
SELECT * FROM
(SELECT cats AS cats1 FROM results WHERE name = :original) AS a,
(SELECT cats AS cats2 FROM results WHERE name = :parsed) AS b
");
$binding = array(
'original' => 'michael',
'parsed' => 'mike'
);
$stmt->execute($binding);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
//if there was a result then output
if($results)
{
echo '<pre>'.print_r($results,1).'</pre>';
}
I get no results with this even though 'michael' is in the database.
If I test for 'original' => 'michael', 'parsed' => 'michael' I get results...both the same of course since I tested the same value for each :
Array
(
[0] => Array
(
[cats1] => 6,11
[cats2] => 6,11
)
)
What I expect is one of the following :
no results meaning neither michael or mike exist
result for cats1 and empty for cats2 (michael exists mike does not)
empty for cats1 and result for cats2 (mike exists michael does not)
No, I cannot use WHERE name = 'michael' OR name = 'mike' because what I do after changes depending if both have results or just one or the other.
This is working as epxected... both always needs a result even if that is empty to return correctly.
$stmt = $dbnet->prepare("
SELECT
IFNULL( (SELECT cats AS cats1 FROM results WHERE name = :original), '') AS a,
IFNULL( (SELECT cats AS cats2 FROM results WHERE name = :parsed), '') AS b
");

how to optimize mysql query in phalcon

i used this query:
$brands = TblBrand::find(array("id In (Select p.brand_id From EShop\\Models\\TblProduct as p Where p.id In (Select cp.product_id From EShop\\Models\\TblProductCategory as cp Where cp.group_id_1='$id'))", "order" => "title_fa asc"));
if($brands != null and count($brands) > 0)
{
foreach($brands as $brand)
{
$brandInProductCategory[$id][] = array
(
"id" => $brand->getId(),
"title_fa" => $brand->getTitleFa(),
"title_en" => $brand->getTitleEn()
);
}
}
TblBrand => 110 records
TblProduct => 2000 records
TblProductCategory => 2500 records
when i used this code, my site donot show and loading page very long time ...
but when i remove this code, my site show.
how to solve this problem?
The issue is your query. You are using the IN statement in a nested format, and that is always going to be slower than anything else. MySQL will need to first evaluate what is in the IN statement, return that and then do it all over again for the next level of records.
Try simplifying your query. Something like this:
SELECT *
FROM Brands
INNER JOIN Products ON Brand.id = Products.brand_id
INNER JOIN ProductCategory ON ProductCategory.product_id = Products.id
WHERE ProductCategory.group_id_1 = $id
To achieve the above, you can either use the Query Builder and get the results that way
https://docs.phalconphp.com/en/latest/api/Phalcon_Mvc_Model_Query_Builder.html
or if you have set up relationships in your models between brands, products and product categories, you can use that.
https://docs.phalconphp.com/en/latest/reference/model-relationships.html
example:
$Brands = Brands::query()
->innerJoin("Products", "Products.brand_id = Brand.id")
->innerJoin("ProductCategory", "ProductCategory.product_id = Products.id")
->where("ProductCategory.group_id_1 = :group_id:")
->bind(["group_id" => $id])
->cache(["key" => __METHOD__.$id] // if defined modelCache as DI service
->execute();
$brandInProductCategory[$id] = [];
foreach($Brands AS $Brand) {
array_push($brandInProductCategory[$id], [
"id" => $Brand->getId(),
"title_fa" => $Brand->getTitleFa(),
"title_en" => $Brand->getTitleEn()
]);
}

Not equal condition with findAll()

I am trying to pull record from a table using the following code
$userId = Yii::$app->user->id;
$lists = PromoLists::findAll(['user_id' => $userId, 'list_type' => 'custom']);
which outputs a query like below
select * from promo_lists where user_id ='$userId' and list_type='custom'
But i am unable to find any thing in the documentation that would help me achieve it with the following condition.
select * from promo_lists where user_id ='$userId' and list_type='custom' and status!='deleted'
as the status is an ENUM field and there are 4 different status
'active','pending','rejected','deleted'
currently i used the following approach
PromoLists::findAll(['user_id' => $userId, 'list_type' => 'custom', 'status'=>['active','pending','rejected']]);
which outputsthe following query
select * from promo_lists where user_id ='$userId' and list_type='custom' and status in ('active','pending','rejected')
which somehow achieves the same thing but this query would need to be edited every time when there is a new status type added to the table column status.
i know i can do this by using PromoLists::find()->where()->andWhere()->all()
but how to check with != / <> operator using findAll().
Simply like this:
PromoLists::find()->where(['and',
[
'user_id' => $userId,
'list_type' => 'custom',
],
['<>', 'status', 'deleted'],
])->all();
Using operator format in condition
http://www.yiiframework.com/doc-2.0/guide-db-query-builder.html#operator-format
PromoLists::find()
->andWhere([
'user_id' => $userId,
'list_type' => 'custom',
['!=', 'status', 'deleted']
])
->all();

query including many tables cakephp 3

Using cakephp 3 I want to have the same result that I will have if I execute the query below (Get all paiements of appartements that belongs to Complex XX) :
SELECT p.*
FROM immeubles i inner join appartements a on i.id=a.immeuble_id
inner join paiements p on p.appartement_id = a.id
where i.complex_id=4
tables used are :
Immeubles (id,name,complex_id(Foreign Key));
Appartements(id, num,immeuble_id(foreign key))
paiements(id,montant,appartement_id(foreign key))
I tried first to extract all appartements that belongs to complex=4 by using the code below but i don't know how to concatenate the results with the table Paiements in order to show all fields of paiements :
$this->Appartements->find()
->join([
'i' => [
'table' => 'Immeubles',
'type' => 'inner',
'conditions' => [
'i.id=Appartements.immeuble_id',
'i.complex_id' => 4
]]]);

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