I would like to restrict results with DISTINCT on two columns using doctrine ORM
My function is like this :
public function findFdvLinkedToPdv($pointVenteCodes){
$queryBuilder =
$this->createQueryBuilder('r')
->leftJoin('r.forceVente', 'forceVente')
->leftJoin('r.pointVente', 'pointVente')
->leftJoin('r.signature', 'signature')
->leftJoin('signature.affaire', 'affaire')
->andWhere('pointVente.code IN (:pointvente_codes)')
->orderBy('forceVente.matricule', 'ASC')
->addOrderBy('pointVente.code', 'ASC')
->addOrderBy('affaire.code', 'ASC')
->addOrderBy('r.type', 'ASC')
->setParameters(array('pointvente_codes' => $pointVenteCodes,))
->select(array(
'forceVente.matricule AS forcevente_matricule',
'pointVente.code AS pointvente_code',
'affaire.code AS affaire_code',
'r.id AS id',
'r.profil AS profil',
'r.type AS type',
'forceVente.nom AS nom',
'forceVente.prenom AS prenom',
'forceVente.email AS email',
'r.deletedAt AS deletedAt'));
return $queryBuilder->getQuery()->getArrayResult();
}
For each forcevente.matricule and each pointVente.code , I have from 2 to 6 rows. I would like to get one row for each couple forcevente.matricule/pointVente.code I have to do a distinct on both columns, but when I try :
->select(array(
'DISTINCT forceVente.matricule AS forcevente_matricule',
'DISTINCT pointVente.code AS pointvente_code',
'affaire.code AS affaire_code', etc ...
I have a doctrine error ...
[EDIT]
I do this in PHP after executing the request to filter the results...
//BEGIN PATCH
$i=0;
$linkedForceVentes2 = array();
foreach ($linkedForceVentes as $item) {
if (!isset($linkedForceVentes2[$item['pointvente_code']][$item['forcevente_matricule']])){
$linkedForceVentes2[$item['pointvente_code']][$item['forcevente_matricule']] = $item;
}else{
unset($linkedForceVentes[$i]);
}
$i++;
}
//END PATCH
I finaly resolved it with a groupBy :
->groupBy('forcevente_matricule', 'pointvente_code', 'type' , 'affaire_code');
Just after the select statement.
Related
I have two tables: products and current_product_attribute_values
I have tried a join query to filter them as per attribute selected by the user but when I try this with an additional condition it gives me 2 results instead of one it is including the first one which is not matching as per query:
select * from `products` inner join `current_product_attribute_values` on `products`.`id` = `current_product_attribute_values`.`product_id` where `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `product_name` LIKE ?
here is my laravel Controller code :
$all = Input::all();
$q = Input::get('search_text');
$att_val = Input::get('attribute_value');
$subcat = Input::get('subcat_id');
$subcat_name = DB::table('subcategories')->where('id', $subcat)->value('subcategory_name');
$brandname = DB::table('brands')->where('subcat_id', $subcat)->value('brand_name');
$brand_id = DB::table('brands')->where('subcat_id', $subcat)->value('id');
$product_count = DB::table('products')->where('brand_id', $brand_id)->count();
if ($q != "") {
// getting multiple same name params
$query = DB::table('products');
$query->join('current_product_attribute_values', 'products.id', '=', 'current_product_attribute_values.product_id');
$j = 0;
foreach ($all as $key => $values) {
//echo 'my current get key is : ' . urldecode($key). '<br>';
if ($key == $name[$j]) {
$query->where('current_product_attribute_values.attribute_id', '=', $att_id_value[$j]);
echo'<br>';
print_r($query->toSql());
echo'<br>';
//echo '<br> key matched and have some value : <br>';
//echo count($values);
if (count($values) >= 1) {
//echo '<br> it has array inside <br>';
foreach ($values as $val) {
// or waali query in same attribute
echo'<br>';
$query->orwhere('current_product_attribute_values.attribute_value_id', '=', $val);
print_r($query->toSql());
echo'<br>';
}
}
$j++;
}
}
$records = $query->toSql();
$query->where('product_name', 'LIKE', '%' . $q . '%');
$records = $query->toSql();
print_r($records);
$products = $query->paginate(10)->setPath('');
$pagination = $products->appends(array(
'q' => Input::get('q')
));
if (count($products) > 0) {
$filters = DB::table('product_attributes')->where('subcategory_id', $subcat)->get(['attribute_title']);
} else {
$filters = array();
}
$categories = categories::where('add_to_menu', 1)->with('subcategories')->with('brands')->get();
$categoryhome = categories::where('add_to_menu', 1)->with('subcategories')->get();
return view('searchfilter')
->with('productsdata', $products)
->with('filtersdata', $filters)
->with('categories', $categories)
->with('categorieshome', $categoryhome)
->with('subcat_name', $subcat_name)
->with('subcat_id', $subcat)
->with('brandname', $brandname)
->with('product_count', $product_count)
->with('querytext', $q);
}
return 'No Details found. Try to search again !';
its easier if you use raw sql as calling db select function. ex:
$query=DB::select("select * from `products` inner join `current_product_attribute_values` on `products`.`id` = `current_product_attribute_values`.`product_id` where `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `product_name` LIKE ?
");
indeed you can concat vars in raw sql if you need to, ex:
$queryBrands = "select id from brands where subcat_id =".$subcat;
//echo $queryBrands
$queryBrands = DB::select($queryBrands);
By looking at your tables, product table with id value 17 has two records in table current_product_attribute_values in column product_id (I assume this column is used as foreign key to product table).
With select *, you select all of the columns from both tables. So it would most likely cause your query to return multiple records.
My suggestions:
Only select the columns you need. Avoid using select * in the long run, i.e. select product.id, product.description, current_product_attribute_values.attribute_values ......
Make use of GROUP BY
Hope these helps.
LARAVEL 5.4 (but probably it's a more general SQL question)
Hello! I have a table with a structure:
Suppose it's my model 'Table'.
I want a query which:
uses (receives) variables :
$id of array ['id', 'string', integer]
where string is '<' or '>'
$status_not_bad = bool;
(if true - include all rows where 'status' !== 'bad' AND 'status' IS NULL);
for example, we are given:
$id = [['id', '>', 0]];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id > 0" returns rows 1 and 3.
but if we given:
$id = [['id', '<', 3]];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id < 3" returns row 1
(it should be same query which return those results using those variables).
Probably you end with something like this:
if ($status_not_bad) {
$nStatus = 'bad';
} else {
$nStatus = 'good';
}
Table::thisquery()->where('status', '<>', $nStatus)
->whereNotNull('status')
->where($id[0], $id[1], $id[2])
->get();
But it would be a good idea to check $id keys first.
Since row id = 3 you need <= in your where statement to have that row included in the result set
$id = ['id', '<=', 3];
So, I this works:
$chain = Sample::when($status_not_bad, function($query){
return $query->where('status', '<>', 'bad')
->orwhereNull('status');
})
->where([$id])
->get();
I have two tables employee_personals where all the personal record of the employee is stored and telephone_bills where the telephone bills paid to a particular employee is stored for each month. Now in my employeePersonalsController.php I have a function called api_show_employees() which is similar to below :
function api_show_employees() {
//$this->autoRender = false;
//Configure::write("debug",0);
$office_id = '';
$cond = '';
if(isset($_GET['office_id']) && trim($_GET['office_id']) != '') {
$office_id = $_GET['office_id'];
$cond['EmployeePersonal.office_id'] = $office_id;
}
if(isset($_GET['telephoneBillTo']) && isset($_GET['telephoneBillFrom']) ) {
if($_GET['telephoneBillTo'] != '' && $_GET['telephoneBillFrom'] != '') {
$cond['TelephoneBill.bill_from'] = $_GET['telephoneBillFrom'];
$cond['TelephoneBill.bill_to'] = $_GET['telephoneBillTo'];
}
}
$order = 'EmployeePersonal.name';
// $employee = $this->EmployeePersonal->find('all');
$employee = $this->EmployeePersonal->find('all',array('order' => $order,'conditions'=>$cond));
//return json_encode($employee);
}
This functions basically finds all the employees who paid bills in the given period. But I am getting an error
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'TelephoneBill.bill_from' in 'where clause'
Models : EmployeePersonal.php:
var $hasMany = array(
'TelephoneBill' => array(
'className' => 'TelephoneBill',
)
);
TelephoneBill.php
public $name = 'TelephoneBill';
var $hasMany = array('EmployeePersonal');
NB: If I skip the bill_from and bill_to conditions, I am getting the results , with TelephoneBill array !
TLDR: use Joins instead.
Details/Notes:
1) it looks like you're using recursive. Don't do that. Use Containable instead.
2) You can't limit the parent model based on conditions against data from a contained/recursive-included table - instead, use Joins.
2b) Or, you could query from the other direction, and query your TelephoneBill with conditions, then contain the EmployeePersonal.
This is my code looks like right now :
$result = Category::with(array(
"getProducts",
"getProducts.getBrand",
"getProducts.getImages",
"getProducts.getDetail",
"getProducts.getTax",
"getProducts.getDiscount",
"getProducts.getAttributes" => function($query) use($_temp){
if($_temp != null){
$query->where_in('attributes.id',$_temp);
}
},
"getSlideshow",
"getSlideshow.getItems",
"getAttributeListing",
"getAttributeListing.getAttributes",
"getAttributeListing.getAttributes.productSpecific"
))
->where('id','=', $category_id)
->first();
Yet, It only filters the getProducts.getAttributes items not the 'getProducts' itself. Is there a way that I can get the Products by attributes?
Note: I am using Laravel 3
I have a simple relation ManyToMany between two entities "article" and "category" (for a blog). I would like to fetch every article with a particular category, but I don't know how to create that query. What I did is :
$query = $em->createQuery(
'SELECT u
FROM SiteBlogBundle:article u
WHERE u.categorie.name = :cat
ORDER BY u.date DESC'
)
->setParameter('cat', '$cateogory')
The line WHERE u.categorie.name = :cat doesn't work. How can I achieve that?
If you are okay with using a query-builder for better readability instead of DQL:
$articles = $em
->getRepository('SiteBlogBundle:Article')
->createQueryBuilder('article')
->leftJoin('article.category', 'category')
->where('category.name = :category_name')
->orderBy('article.date', 'DESC')
->setParameter('category_name', $category->getName())
->getQuery()
->getResult()
;
But i would strongly advise you to put this query into the repository like this:
// ArticleRepository.php
public function findArticlesByCategoryName($name)
{
return $this->createQueryBuilder('article')
->leftJoin('article.category', 'category')
->where('category.name = :category_name')
->orderBy('article.date', 'DESC')
->setParameter('category_name', $name)
->getQuery()
->getResult()
;
}
Then inside your controller just do:
public function getArticles(Category $category)
{
$em = $this->getDoctrine()->getEntityManager();
return $em->
getRepository('SiteBlogBundle:Article')
->findArticlesByCategoryName($category->getName())
;
}