MySQL Syntax error: ORDER BY clause is not in GROUP BY - php

I have a query where I want to order by shipping_date but I get this error:
QueryException in Connection.php line 770:
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression 1 of
ORDER BY clause is not in GROUP BY clause and contains nonaggregated
column 'device.devices.shipping_date' which is not functionally
dependent on columns in GROUP BY clause; this is incompatible with
sql_mode=only_full_group_by (SQL: select count(*) as device,
DATE_FORMAT(shipping_date,"%M %Y") as year from `devices` where
`shipping_date` is not null and `internal_use` = 0 group by `year` order by `shipping_date` asc)
My code:
$sold_devices = Device::selectRaw('count(*) as device, DATE_FORMAT(shipping_date,"%M %Y") as year')
->whereNotNull('shipping_date')
->where('internal_use', '=', 0)
->groupBy('year')
->orderBy('shipping_date', 'asc')
->pluck('device', 'year');
any help?
Thanks

You have to specify the exact select column in your group by: in your case
->groupBy('DATE_FORMAT(shipping_date,"%M %Y")')
->orderBy('DATE_FORMAT(shipping_date,"%M %Y")', 'asc')
Generally speaking, you can't use column aliases in where, group by and order by clauses.
Edit
To change the ordering criteria you can use the numeric value of the month instead of its name:
->groupBy('DATE_FORMAT(shipping_date,"%M %Y")')
->orderBy('DATE_FORMAT(shipping_date,"%Y%c")', 'asc')

let's try this.
it will work...
->groupBy(DB::raw('DATE_FORMAT(shipping_date,"%M %Y")'))
->orderBy(DB::raw('DATE_FORMAT(shipping_date,"%M %Y"))','asc')

Related

How to solve Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous in laravel

I have a belongsToMany relationship between the students and departments. Now i want to fetch all the departments of students where subject_id of departments is null. I below code but it gives me the following error
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous (SQL: select * from departments where subject_id is null and exists (select * from students inner join department_student on students.id = department_student.student_id where departments.id = department_student.department_id and id = 16 and students.deleted_at is null))
$departments=Department::where('subject_id','=',null)
->whereHas('students',function($student){
$student->where('id',Auth::id());
})
->get();
dd($departments);
Any help will be appreciated
You should specify the table name where you are referencing the id to avoid the ambiguity.
$departments=Department::where('subject_id','=',null)
->whereHas('students',function($student){
$student->where('student.id',Auth::id()); //Notice the student.id instead of id
})->get();
We also can use like this
->whereHas('students',function($student){
$student->where('student.id', '=', Auth::id()); //Like this
})->get();

Add extra SELECT expression result to the existing entity

I have the project that allows to rate a company in many aspects. The following diagram could help you to understand the relations in my database. Of course, I have deleted from the scheme the fields, that are not important in the context of my problem.
Currently, in my repository class of the Company entity, I am searching for companies using QueryBuilder and returning an instance of \Doctrine\ORM\Tools\Pagination\Paginator.
The below code is responsible for fetching companies:
public function search(CompanySearchQuery $command): Paginator
{
$qb = $this->createQueryBuilder('c')
->setFirstResult($command->getOffset())
->setMaxResults($command->getMaxResults())
->orderBy('c.name', 'ASC');
... plus extra "where" conditions
return new Paginator($qb, true);
}
I wonder how I can attach the average score to each company using QueryBuilder and Paginator.
Here is the native SQL that allows me to get data I need:
SELECT
c.id,
c.name,
AVG(o2.score) as score
FROM
company c
LEFT JOIN
opinion o ON c.id = o.company_id
LEFT JOIN
opinion_scope o2 ON o.id = o2.opinion_id
GROUP BY
c.id
My question is: Is it possible to add averageScore property to the Company class and map it from QueryBuilder result?
I tried to rewrite my SQL query to use with the existing code:
$qb = $this->createQueryBuilder('c')
->select('c', 'AVG(s.score)')
->leftJoin('c.opinions', 'o')
->leftJoin('o.scopes', 's')
->groupBy('c.id')
->setFirstResult($command->getOffset())
->setMaxResults($command->getMaxResults())
->orderBy('c.name', 'ASC')
;
With the above code I get database exception as following:
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #14 of
SELECT list is not in GROUP BY clause and contains nonaggregated column
'database.o1_.score' which is not functionally dependent on columns in GROUP BY
clause; this is incompatible with sql_mode=only_full_group_by").
The SQL query that is executed for the above QueryBuilder is:
SELECT
DISTINCT id_8
FROM
(
SELECT
DISTINCT id_8,
name_9
FROM
(
SELECT
c0_.updated_at AS updated_at_0,
c0_.description AS description_1,
c0_.website AS website_2,
c0_.email AS email_3,
c0_.phone AS phone_4,
c0_.street AS street_5,
c0_.postal_code AS postal_code_6,
c0_.city AS city_7,
c0_.id AS id_8,
c0_.name AS name_9,
c0_.slug AS slug_10,
c0_.created_at AS created_at_11,
AVG(o1_.score) AS sclr_12,
o1_.score AS score_13,
o1_.opinion_id AS opinion_id_14,
o1_.type_id AS type_id_15
FROM
company c0_
LEFT JOIN opinion o2_ ON c0_.id = o2_.company_id
LEFT JOIN opinion_scope o1_ ON o2_.id = o1_.opinion_id
GROUP BY
c0_.id
) dctrn_result_inner
ORDER BY
name_9 ASC
) dctrn_result
LIMIT
2 OFFSET 0
I do not understand why Doctrine adds the following fragment:
o1_.score AS score_13,
o1_.opinion_id AS opinion_id_14,
o1_.type_id AS type_id_15
The issue seems to be that you're trying to select every column from 'c', which is your resulting table from performing two LEFT JOINs. Instead, you need to be specifying a from clause for the company table:
$qb = $this->createQueryBuilder()
->select('c', 'AVG(s.score)')
->from('company', 'c')
->leftJoin('c.opinions', 'o')
->leftJoin('o.scopes', 's')
->groupBy('c.id')
->setFirstResult($command->getOffset())
->setMaxResults($command->getMaxResults())
->orderBy('c.name', 'ASC')
;
This will avoid including o1.score is your returned columns, which is what that error is referencing

I found Error in query when i join with another table

When i join one table to another then i got this error. i put as keyword but its not working it give me error like field not found how can i solve this error
Code:
Product::leftjoin('reviews','products.id','=','reviews.productID')
->select(array('products.*',
DB::raw('AVG(rating) as ratings_average')
))
->where(function($query) use ($categoriesID,$brands,$priceArray,$ratingArray)
{
$query->whereIn('categoryID',$categoriesID);
if(count($brands) > 0)
{
$query->whereIn('brandID',$brands);
}
$query->whereBetween('productSellingPrice',$priceArray);
if(count($ratingArray) > 0)
{
$query->whereBetween('ratings_average',$ratingArray);
}
})
->groupBy('products.id')
->get();
Error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ratings_average' in 'where clause' (SQL: select `products`.*, AVG(rating) as ratings_average from `products` left join `reviews` on `products`.`id` = `reviews`.`productID` where (`categoryID` in (9, 11, 31) and `productSellingPrice` between 50 and 5000 and `ratings_average` between 1 and 2) group by `products`.`id`)
Instead of rating array you can find out $minRating and maxRating. By these two value you can run you query like this:
$query->whereBetween('rating',[$minRating,$maxRtaing]);
The problem is a SQL problem, and it has to do with scoping. I'm not well versed in laravel's API, but the SQL generated (based on your helpful error message) is:
select `products`.*, AVG(rating) as ratings_average
from `products` left join `reviews` on `products`.`id` = `reviews`.`productID`
where (`categoryID` in (9, 11, 31) and `productSellingPrice` between 50 and 5000
and `ratings_average` between 1 and 2) group by `products`.`id`)
The problem is that the ratings_average calculated column belongs to the GROUP BY scope. The only way to reference that column is in a HAVING statement. Your SQL statement would look like this:
select `products`.*, AVG(`ratings`.`rating`) as ratings_average
where `products`.`id` = `reviews`.`productId`
group by `products`.`id`
having (`categoryID` in (9, 11, 31) and `productSellingPrice` between 50 and 5000
and `ratings_average` between 1 and 2)
Technically speaking, the first two clauses in the having statement above could be in your WHERE clause, but the ratings_average named column can only be referenced in the HAVING clause. Both WHERE and HAVING restrict your results, but HAVING is evaluated after the grouping took place.

Laravel groudby use day()

my sql is
select * from patient group by day(created_at) order by created_at"
but my use laravel ,i think use Model
Patient_Model::groupBy("DAY(created_at)")
->orderBy("created_at","desc")
->get();
this is error :
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'DAY(created_at)' in 'group statement' (SQL: select * from `patients` group by `DAY(created_at)` order by `created_at` desc)
How uese day() in laravel5.1?
You should be able to use it with DB::raw() like so :
Patient_Model::
->groupBy(DB::raw('DAY(created_at)'))
->orderBy("created_at","desc")
->get();
Use this instead
groupBy(\DB::raw("DAY(created_at)"))

Cannot retrieve data from database - Error 1241

Error
SQL query: Documentation
SELECT status.id AS id, status.status
FROM STATUS
WHERE id
IN (
SELECT student.id, student.fname
FROM student,
STATUS WHERE student.id =14
)
ORDER BY status_id DESC
MySQL said: Documentation
#1241 - Operand should contain 1 column(s)
The SELECT inside the IN() should not select more than one column.
in the subuery "SELECT student.id, student.fname" you have to extract only one field

Categories