yii cdbcriteria: complex joins - yii

I recently started a project using Yii and I'm trying to get used to the query builder. Now, I want to make a query using joins and access the joining tables' data in the query but I haven't been able to get the following to work:
My (simplified) db-tables:
customer(#id, name)
employee(#id, name)
customer_employee(#customerid, #employeeid)
accounting(#id, customerid, started_date, finished_date, month, year)
many-to-many relation between customer and employee
one-to-many relation between customer and accounting
I want to execute the following query, which would select all the customers associated with a certain employee and display their accounting status (started_date & finished_date) if applicable (otherwise null).
The following query works perfectly, it's just that I can't get it to work with the cdbcriteria and Yii query builder: (also, hardcoded id is just for this example)
SELECT name, started_date, finished_date
FROM customer
RIGHT JOIN customer_employee ON customer.id=customer_employee.customerid
LEFT JOIN accounting ON customer.id=accounting.customerid
WHERE customer_employee.employeeid=2';
Please help!

1.
createCommand
Yii::app()->db->createCommand()
->select('name, started_date, finished_date')
->from('customer c')
->rightJoin('customer_employee ce', 'c.id=ce.customerid')
->leftJoin('accounting a', 'c.id=a.customerid')
->where('ce.employeeid=:id', array(':id'=>2))
->queryRow();
2.
CdbCriteria
$criteria = new CDbCriteria;
$criteria->select = 'name, started_date, finished_date';
$criteria->join = 'RIGHT JOIN customer_employee ON customer.id=customer_employee.customerid ';
$criteria->join .= 'LEFT JOIN accounting ON customer.id=accounting.customerid';
$criteria->condition = 'customer_employee.employeeid=:id';
$criteria->params = array(':id'=>2);
$customers = Customers::model()->find($criteria);
*.
don't forget the rules: http://www.yiiframework.com/doc/guide/1.1/en/database.arr
I didn't tested your SQLs, but if worked for you, these should, also work in Yii.

$criteria = new CDbCriteria();
$criteria->select = "name, started_date, finished_date";
$criteria->join = "RIGHT JOIN customer_employee ON customer.id=customer_employee.customerid LEFT JOIN accounting ON customer.id=accounting.customerid";
$criteria->condition = "customer_employee.employeeid=2";
$models = Customer::model()->findAll($criteria);
This is how to get data with command for table customer_employee
foreach($model as $value)
{
}

A bit late in the day but see this post on my blog which addresses both parts of this difficult sub-query style SQL.
Firstly, to build a Search that relies on attributes from other models
Secondly, to use related models simply without using the full Yii AR model
http://sudwebdesign.com/yii-parameterising-a-sub-select-in-sql-builder/932

I have not run it but some thing like the following is what you need
$criteria = new CDbCriteria();
$criteria->select = "name, started_date, finished_date";
$criteria->join = "RIGHT JOIN customer_employee ON customer.id=customer_employee.customerid LEFT JOIN accounting ON customer.id=accounting.customerid";
$criteria->condition = "customer_employee.employeeid=2";
$models = Customer::model()->findAll($criteria);

Related

SQL Postgre to show 1 data if get same some multiple data and how to implement to laravel query

i want to ask about sql in postgresql, i got data from join with 3 table, i got the result but i got multiple data like this image
result
and here my sql code in postgresql
select users.* from users inner join model_has_roles on model_has_roles.model_id = users.id
left join roles on roles.id = model_has_roles.role_id where roles.name not in ('job-seeker') order by users.name asc
how to fix this query where i got the multiple data only 1 data to show.
and i want this sql to implement to laravel query and here my code now
public function getAccountList(){
$req = app(Request::class);
// $getAccount = User::query();
$getAccount = User::join('model_has_roles', function($join) {
$join->on('users.id', '=', 'model_has_roles.model_id');
})->leftJoin('roles', function($join){
$join->on('model_has_roles.role_id', '=', 'roles.id');
});
$getAccount->whereNotIn('roles.name', ['job-seeker']);
if ($q = $req->query('q')) {
$searchTerm = trim(strtolower($q));
$getAccount->whereRaw(
'LOWER(users.name) like (?) or LOWER(users.email) like (?)',
["%{$searchTerm}%", "%{$searchTerm}%"]
);
}
// $getAccount->get()->unique('name');
$getAccount->select(['users.*']);
$paginator = $this->pagination($getAccount);
return $this->paginate($paginator, new UserTransformer);
}
how to fix the query only 1 data to show not the multiple same data. thank you for helping me. God Bless You
use distinct()
$data = DB::table('test')->[your query builder]->distinct()->get();
Laravel Query Builder Docs
Just change a bit to make it related to your query builder

Prestashop module SQL Query to get id_products from a specific feature value

I'm currently working with a module called "Leo Parts Filter" on prestashop, which sort id_products by make, model, year and device in a database "ps_leopartsfilter_product".
When i call a make, model, year a device that have an id_product in this table, prestashop show this id_product.
public static $definition = array(
'table' => 'leopartsfilter_product',
'primary' => 'id_product',
'multilang' => false,
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'leopartsfilter_product` WHERE 1=1 ';
if ($id_product != null && (int) $id_product) {
$sql .= ' AND id_product =' . (int) id_product;
}
I would like to change the way id_product is called, instead of calling only this id_product according this way :
I would like to query all products where the feature_id = 212 and where the feature_value_lang = id_product.
I tried to adapt this query but i can't make it work correctly (no data showing)
SELECT id_product, fl.name, value, pf.id_feature
FROM '._DB_PREFIX_.'feature_product pf
LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature =212 AND fl.id_lang = '.(int)$context->language->id.')
LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fvl.id_feature_value = pf.id_feature_value AND fvl.id_lang = '.(int)$context->language->id.')
LEFT JOIN '._DB_PREFIX_.'feature f ON (f.id_feature = pf.id_feature)
'.Shop::addSqlAssociation('feature', 'f').'
WHERE fvl.`value` = '['id_product']'
GROUP BY id_product
ORDER BY f.position ASC
';
I'm not good at SQL so don't blame me, i learned everything by my way and i try to build my own company website, this module is all i need to finish.
If someone want some money for help, i'm open to give rewards to make it work.
Thanks
Your second query has nothing to do with the Leo Parts Filter module, since it only queries native Prestashop feature tables and not those of the Leo module itself, so your request is not very clear.
If you need to rely on basic features, it must be clear to you that the relationship between id features / id feature values and id products is all in the ps_feature_product table, so if you want products that have id_feature_value = 212 you just need a simple
SELECT id_product FROM ps_feature_product WHERE id_feature_value = 212;

I need to get Subject name with total number of Book

I have a SQL Query which I want to convert in Linq or want to show data
as pictured here
Here is the query:
select sae_subcategorymaster.subject, count(sae_tblbookdetail.title)
from sae_tblbookdetail inner join sae_subcategorymaster
on sae_subcategorymaster.subject=sae_tblbookdetail.subject
group by sae_subcategorymaster.subject
What is a simple way to do this?
Grouping is supported in LinqEF. Provided you have your entities related. (Books have a reference to their subcategory.)
var totals = context.Books
.GroupBy(book => book.SubCategory.Subject)
.Select(group => new
{
Subject = group.Key,
BookCount = group.Count()
}).ToList();

How to get posts from a category using SQL query in Wordpress

I need to get posts from a category using SQL query in Wordpress, so i use get_resilts but it returns an empty array...please could someone tell me what is wrong in my code...? thanks a lot
$wpdb->get_results("
SELECT ID, post_date
FROM {$wpdb->prefix}posts
LEFT JOIN $wpdb->term_relationships ON
($wpdb->posts.ID = $wpdb->term_relationships.object_id)
LEFT JOIN $wpdb->term_taxonomy ON
($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE $wpdb->posts.post_type = 'post'
AND $wpdb->term_taxonomy.taxonomy = 'category'
AND $wpdb->term_taxonomy.term_id = 18
);
Is there a particular need to use an SQL query with $wpdb?
This can be easily be achieved using WordPress functions:
$args = array( 'post_type' => 'post', 'category' => 18 );
$myposts = get_posts( $args );
If using SQL is an absolute requirement you'll want to fix your query.
This is correct:
FROM {$wpdb->prefix}posts
This is not:
LEFT JOIN $wpdb->term_relationships ON

Yii model findAll() and count() return different number of results

UPDATED: see the end of the question
I'm working with Yii (and RESTFullYii in particular but I doubt that is relevant to the question)
There is a CDbCriteria for a model:
$criteria = new CDbCriteria(
array(
'together' => true,
'with' => array(
'roles'=> array(
'having' => "roles.role IN ($userRoles)"
))
)
);
$count = $model->count($criteria);
$result= $model->findAll($criteria);
While the findAll() method returns only 3 records (which is good) the count() method returns 13 which is the total number of records in the table represented by the $model
I've enabled query logging in MySQL and I found out that the two query generated by Yii is completely different
SELECT `t`.`id` AS `t0_c0`,
`t`.`name` AS `t0_c1`,
`t`.`description` AS `t0_c2`,
`t`.`enabled` AS `t0_c3`,
`t`.`issuegroup_id` AS `t0_c4`,
`t`.`role_id_exec` AS `t0_c5`,
`t`.`require_attachment` AS `t0_c6`,
`roles`.`id` AS `t1_c0`,
`roles`.`role` AS `t1_c1`,
`roles`.`enabled` AS `t1_c2`,
`roles`.`description` AS `t1_c3`
FROM `issuetype` `t`
LEFT OUTER JOIN `role_has_issuetype` `roles_roles` ON
(`t`.`id`=`roles_roles`.`issuetype_id`)
LEFT OUTER JOIN `role` `roles` ON
(`roles`.`id`=`roles_roles`.`role_id`)
HAVING (roles.role IN ('user'))
LIMIT 100
The other query:
SELECT COUNT(DISTINCT `t`.`id`)
FROM `issuetype` `t`
LEFT OUTER JOIN `role_has_issuetype` `roles_roles` ON
(`t`.`id`=`roles_roles`.`issuetype_id`)
LEFT OUTER JOIN `role` `roles` ON
(`roles`.`id`=`roles_roles`.`role_id`)
Is this the normal behavior for the findAll() and count() methods or did I do something I shouldn't have done or is this a bug in Yii?
And how to get the actual count of the records properly?
count($model->findAll($criteria)) seems to be working fine but is this the correct solution or is it just a workaround?
(From a performance viewpoint I think it might be better than the actual count() because I'm running the same query twice which is cached by the MySQL server)
UPDATE:
I've asked the same question on GitHub and Paul Klimov kindly pointed out that it is unnecessary for the 'having' and 'group' clauses to be in the joined table and it is perfectly OK to move it out of the 'with' see it here: https://github.com/yiisoft/yii/issues/3297
Yii had some problem with Having criteria while using count method from ActiveRecord, but it is fixed in newer Yii versions: https://github.com/yiisoft/yii/pull/2167
You need to clone your model before count() or findAll() method applying:
$result= $model->findAll($criteria);
$modelClone = clone $model;
$count = $model->count($criteria);